Escrevendo a saída “tail -f” para outro arquivo

29

Como continuação de meu último post onde usei grep & tail -f para encontrar ocorrências de eventos "raros". Eu gostaria de gravar isso em outro arquivo.

Eu tentei transformar

tail -f log.txt | egrep 'WARN|ERROR'

em

tail -f log.txt | egrep 'WARN|ERROR' | tee filtered_output.txt

O arquivo é criado, mas nada é preenchido, isso é um problema de cache ou não? Como eu obteria um acréscimo em tempo real da saída da minha cauda a um novo arquivo?

    
por Mike 23.10.2009 / 17:43

5 respostas

39

A memória intermédia é o problema.

Faça assim,

tail -f log.txt | egrep --line-buffered 'WARN|ERROR' | tee filtered_output.txt
#                       ^^^^^^^^^^^^^^^

Confirmado para trabalhar no Cygwin também.

    
por 23.10.2009 / 17:59
5

É provavelmente um problema de buffer. Veja esta postagem SO ao desativar o buffer automático ao usar pipes . Você pode usar o comando unbuffer de expect :

$ unbuffer tail -f log.txt | egrep 'WARN|ERROR' | tee filtered_output.txt

Editar : Como você tem um pipeline mais longo, provavelmente precisará desabafar cada comando (exceto o último):

$ unbuffer tail -f log.txt | unbuffer egrep 'WARN|ERROR' | tee filtered_output.txt

Editar 2 : unbuffer está disponível no Cygwin do pacote expect source (por exemplo, expect-20030128-1-src.tar.bz2 , encontrado na pasta expect/examples ), mas é um script muito curto. Se você tiver o pacote expect já instalado, basta colocar isso em um script chamado unbuffer no diretório /usr/local/bin :

#!/usr/bin/expect --
# Description: unbuffer stdout of a program
# Author: Don Libes, NIST

eval spawn -noecho $argv
set timeout -1
expect

No Debian, o comando unbuffer é fornecido no pacote expect-dev e é instalado como expect_unbuffer .

    
por 23.10.2009 / 17:51
3

Ao usar um comando que realmente não 'termina' (como tail -f ), isso realmente não funciona ou está bem (de jeito nenhum).

You should be able to redirect the output to a text file. Try this:

tail -f log.txt | egrep 'WARN|ERROR' > filtered_output.txt
    
por 23.10.2009 / 17:47
2

Esta é a versão de unbuffer que eu tenho:

#!/usr/bin/expect --
# Description: unbuffer stdout of a program
# Author: Don Libes, NIST

if {[string compare [lindex $argv 0] "-p"] == 0} {
    # pipeline
    set stty_init "-echo"
    eval spawn -noecho [lrange $argv 1 end]
    close_on_eof -i $user_spawn_id 0
    interact {
    eof {
        # flush remaining output from child
        expect -timeout 1 -re .+
        return
    }
    }
} else {
    set stty_init "-opost"
    set timeout -1
    eval spawn -noecho $argv
    expect
}
    
por 23.10.2009 / 20:28
2

Como outros apontaram, você pode usar o utilitário unbuffer do Expect.

Observe, no entanto, que, dependendo do sistema e da versão disponível do Expect, talvez seja necessário usar a opção -p para unbuffer. Citando a página man:

   Normally, unbuffer does not read from stdin.  This simplifies use of unbuffer in some situations.  To use unbuffer in a  pipeline,  use
   the -p flag.  Example:

           process1 | unbuffer -p process2 | process3

Então você pode precisar desta invocação:

unbuffer -p tail -f log.txt | unbuffer -p egrep 'WARN|ERROR' | tee filtered_output.txt

BTW, consulte este artigo para obter explicações detalhadas sobre o problema de buffer de saída: link

    
por 25.02.2010 / 14:22