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.
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?
É 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
.
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
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
}
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