A saída de strings Grepping fica difícil

4

Eu escrevi o seguinte código para determinar quais arquivos um programa grava. Eu quero capturar os nomes de arquivo, é claro.

strace -f -t -e trace=file -p 8804 2>&1 | grep -oP "\"(.*)\".*O_WRONLY"

Isso gera algo como

/tmp/11111111.txt", O_WRONLY

O problema é que não posso canalizar a saída de tudo isso para qualquer comando

strace -f -t -e trace=file -p 8804 2>&1 | grep -oP "\"(.*)\".*O_WRONLY" | echo
# does not show anything

E também não posso salvar a saída de tudo isso para uso posterior:

strace -f -t -e trace=file -p 8804 2>&1 | grep -oP "\"(.*)\".*O_WRONLY" > asd.out
# file is empty

Sua ajuda é apreciada. :)

    
por Rápli András 18.01.2017 / 15:26

2 respostas

3

Você pode gravar a saída em um arquivo (com strace -o asd.out ) e depois aplicá-lo:

Do manual da strace:

-o filename Write  the  trace  output to the file filename rather than 
to stderr.  Use filename.pid if -ff is used. If the argument begins with
'|' or with '!' then the rest of the argument is treated as a command
and all output is piped to it. This is convenient for piping the
debugging output to a program without affecting the redirections of 
executed programs.
    
por 18.01.2017 / 15:32
0

Correu para o mesmo problema hoje em dia.

FWIW você pode usar | cat em vez de | echo no seu exemplo, echo aparentemente não faz nada por padrão sem parâmetros.

Na minha caixa strace ls 2>&1 | grep "execve" > asd.out realmente funciona OK ... então você está fazendo certo.

Meu palpite é que o problema está em "anexar" como strace -p xxx , porque normalmente você precisa atingir ctrl+c para sair dele e os buffers intermediários em sua cadeia de comando não são ativados .

Então, isso funciona para mim (acho que ele libera uma nova linha porque ela detecta a saída para "a tela" / terminal / tty):

strace ruby -e "sleep" 2>&1 | grep execve

mas isso não acontece

strace ruby -e "sleep" 2>&1 | grep execve > my_output_file

(Eu acho que porque o redirecionamento final é "não para um tty", então ele usa um buffer interno maior de 4k ou algo assim, ou usa um buffer interno ao invés de buffering "by line").

Mas usando uma dica de aqui , isso funciona:

strace ruby -e "sleep" 2>&1 | stdbuf -oL grep execve > me

Coisas bem estranhas. De uma maneira desconcertante. E minha teoria é que com cadeias mais longas (ex: grep | grep | grep o tamanho do buffer cresce linearmente ... 4k de cada vez ... incluindo aquele que o grava finalmente no disco ...)

Outra coisa que pode ajudar é inserir um peeker "output to screen" em sua cadeia, que aparentemente é tee /dev/tty :

strace ruby -e "sleep" 2>&1 | tee /dev/tty | grep execve > my_output_file

Então, pelo menos, você o verá na tela, mesmo que nunca chegue ao arquivo de saída.

De qualquer forma, o que é necessário é que o strace registra como "normal" stderr (portanto, se estiver "executando um processo", por exemplo, strace ls , a saída do processo e strace será mista ). Você pode evitar a mistura usando o parâmetro -o output_file .

Também tenha cuidado, você deve redirecionar o stdout primeiro, depois stderr, ex:

progname >out.txt 2>&1

a ordem é importante, não pode ser o contrário.

    
por 21.08.2018 / 21:53