Espreite o conteúdo de stdin

7

Eu estou tentando depurar um aplicativo Linux que pode receber comandos via stdin, e seria realmente útil ser capaz de ver tudo o que é gravado no stdin.

Minha primeira abordagem foi executar sudo cat /proc/$pid/fd/0 , mas acontece que é uma abordagem inválida, já que cat e meu processo estão tentando consumir o conteúdo desse descritor de arquivo, e apenas um processo pode vencer a corrida .

Outra abordagem seria usar o tail, mas isso não funcionaria por razões descritas aqui .

Eu poderia adicionar facilmente o log de depuração ao meu aplicativo, e isso resolveria o problema, mas estou interessado em saber se há uma abordagem mais geral que está faltando.

    
por John Saxton 09.07.2015 / 23:22

3 respostas

3

strace ?

Exemplo abaixo. Inicie um processo cat que esteja lendo stdin e escrevendo para / tmp / foofile. Encontre o pid, force-o. E na janela original do gato, insira um texto, pronto.

# cat >/tmp/foofile


# ps -ef|grep cat
steve     2134  1801  0 22:25 pts/2    00:00:00 cat
# strace -fp 2134
Process 2134 attached
read(0, "test\n", 65536)                = 5
write(1, "test\n", 5)                   = 5
read(0,

Para extrair as leituras do descritor de arquivo 0:

strace -fp 2134 -e trace=read -o "|grep read.0,"
    
por 09.07.2015 / 23:27
0

No linux, você pode endereçar os descritores de arquivos de um aplicativo como arquivos nomeados em /dev/fd/[0-9] . E o que você definitivamente pode fazer com um arquivo nomeado e um fluxo de entrada é tee da entrada nesse arquivo e para stdout. E então o que eu costumo fazer quando me encontro em sua situação (como sempre faço) é tee de entrada para meu aplicativo de leitura e para /dev/fd/2 - stderr.

Assim:

seq 10 | tee /dev/fd/2 | wc -c
1
2
3
4
5
6
7
8
9
10
21

Claro, mesmo se você não estivesse em um sistema Linux, a mesma coisa poderia ser feita portavelmente - se menos especificamente em alguns casos - apenas fazendo ...| tee /dev/tty | ...

Se você está falando sobre o terminal quando diz stdin (como seu link indica) , então você ainda pode fazer a mesma coisa, embora possa ser um pouco mais complicado dessa maneira por causa do buffer de linha do kernel. Então, o que eu faria nesse caso é registrar todo tty i / o agrupando meu comando em luit - porque eu acho que o mais conveniente dos dois - embora script também pudesse funcionar da mesma forma maneira.

luit provavelmente já está instalado em seu sistema - normalmente é empacotado com xterm - e é uma ferramenta cli muito simples destinada a fazer traduções UTF-8 (cuja função pode ser desativada completamente via cli switch, mas eu nunca encontrei uma razão para fazê-lo) para aplicações de terminal que não entendem isso.

Funciona colocando em camadas a sua própria pty - para a qual possui o master fd - abaixo da camada tty atual e copiando toda a i / o da sessão atual para sua camada filha, onde ele executa o aplicativo solicitado. Como ele é o dono do master, ele pode facilmente duplicar todos os i / o que lê / escreve em outro lugar, e fornece um meio conveniente de fazer isso:

luit -olog /dev/fd/2 sh -c 'read var; echo "$var"'
eecchhoo  tthhiiss  vvaarr??????

echo this var???
echo this var???

Onde, como você pode ver, luit logs para o arquivo -olog nomeado, todos os dados recebidos do terminal são recebidos assim.

Usar /dev/fd/2 não é tão útil nesse caso - pois todo o i / o acaba no mesmo lugar duas vezes. Eu geralmente prefiro abrir um segundo terminal, consultar seu nome com o comando tty e usar esse nome /dev/pts/[0-9] como luit / script chamado outfile - que copia todos os i / o para ambos terminais simultaneamente - para que eu possa ler / rever em um, e interagir com ele por outro. tee pode ser usado para fazer a mesma coisa na maioria dos casos, mas normalmente não tem a vantagem do fim mestre de um artigo para recomendá-lo.

Se o seu objetivo é exatamente o que você diz - copiar para sua revisão toda a entrada de algum processo - então você provavelmente faria o melhor para se concentrar na entrada. strace é útil para muitas coisas, mas se você estiver tentando obter um relatório preciso de comportamento típico, é lógico que provavelmente você modifique esse comportamento o mínimo possível ao coletar seu relatório. Em outras palavras, se você quiser entrada, copiar entrada, não insira um processo pai de depuração que irá -TRAP e pause seu processo toda vez que fizer um syscall.

    
por 10.07.2015 / 02:02
-1

Uma possibilidade (se isso não quebrar outras coisas) é inserir uma chamada para tee . O comando tee duplica os dados, assim você pode ter uma cópia indo para o seu aplicativo e outra indo para a saída de depuração. Em vez de invocar your_application , organize para invocar tee input.log | your_application . Se a entrada para o seu aplicativo era um arquivo, esta não é uma alteração invasiva, mas se não fosse um pipe, isso tornaria um pipe, o que tem consequências (por exemplo, um pipe não é procurado).

Outra possibilidade é rastrear as operações de leitura de arquivos que seu aplicativo realiza. Você pode fazer isso com strace :

strace -e read=0 -e trace=read -e signal=none your_application 2>&1 |
grep '^ |'
    
por 10.07.2015 / 02:19