Gravando saída "tail -f" para outro arquivo


34

Como continuação do meu último post, onde eu costumava grep & tail -fencontrar ocorrências de eventos "raros". Eu gostaria de gravar isso em outro arquivo.

Eu tentei virar

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

para dentro

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

O arquivo é criado, mas nada é preenchido. Esse é um problema de armazenamento em cache ou não? Como obter um anexo em tempo real da saída da minha cauda em um novo arquivo?

Respostas:


44

O buffer é o problema.

Faça assim,

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

Confirmado para trabalhar em Cygwin também.


6

Provavelmente é um problema de buffer. Veja este post do SO sobre a desativação do buffer automático ao usar tubos . Você pode usar o unbuffercomando em expect:

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

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

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

Edição 2 : unbufferestá disponível no Cygwin a partir do expectpacote fonte (por exemplo, expect-20030128-1-src.tar.bz2 , encontrado na expect/examplespasta), mas é um script muito curto. Se você já possui o expectpacote, basta colocar isso em um script chamado unbufferem seu /usr/local/bindiretório:

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

eval spawn -noecho $argv
set timeout -1
expect

No Debian, o unbuffercomando é fornecido no expect-devpacote e é instalado como expect_unbuffer.


existe uma maneira de fazer isso com o cygwin?
2355 Mike

informações adicionais sobre o uso no cygwin; você precisará do expectpacote.
quack quixote

Obrigado, não posso tentar até segunda-feira agora, infelizmente. Será atualizado então.
2355 Mike

4

Ao usar um comando que realmente não 'termina' (como tail -f), isso realmente não funciona ou não é tão bom assim.

Você deve conseguir redirecionar a saída para um arquivo de texto. Tente o seguinte:

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

1
Isso não parece funcionar.
2355 Mike

2

Esta é a versão unbufferque 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
}

+1 obrigado pela informação adicional. não sei se é compatível com cygwin, mas parece um script mais inteligente.
quack quixote

2

Como outros já apontaram, você pode usar o unbufferutilitário do Expect.

Observe, no entanto, que, dependendo do seu sistema e da versão disponível do Expect, pode ser necessário usar a -popção para remover o buffer. Citando a página de manual:

   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

Portanto, 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 uma explicação completa do problema do buffer de saída: http://www.pixelbeat.org/programming/stdio_buffering/

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.