finalizar um arquivo de log, mas mostrar apenas linhas específicas

29

Estou seguindo um arquivo de log com o sinalizador -f. Então, eu estou colocando isso no grep, para encontrar apenas linhas que contenham "X". Isso está funcionando perfeitamente bem. Agora quero canalizar isso novamente para outro grep, que removerá todas as linhas que contêm "Y". Quando adiciono o segundo canal, o arquivo para de atualizar e parece que não há dados chegando.

Este é o comando que funciona: tail -f my_file.log | grep "X"

Este é o comando que não: tail -f my_file.log | grep "X" | grep -v "Y"

Como devo estruturar isso para que o comando funcione?

Ori Horev
fonte
1
tente fazer um tubo por um tubo, mude a sequência, faça tail -f file|grep -v "Y". se a saída estiver correta, prossiga para acrescentar grep "X".
Aizuddin Zali

Respostas:

38

Como a saída de grepé armazenada em buffer, use a --line-bufferedopção de greppara ativar o buffer de linha:

tail -f /path/to/log | grep --line-buffered 'X' | grep -v 'Y'

Se o seu grepnão tiver a opção, você pode usar stdbufcomo alternativa:

tail -f /path/to/log | stdbuf -oL grep 'X' | grep -v 'Y'
heemail
fonte
1
Gostaria de saber como stdbufinforma libstdbuf.soquais configurações usar.
kasperd
@kasperd: Variáveis ​​de ambiente.
Node Eldredge
1
@NateEldredge Eu já procurei variáveis ​​de ambiente na saída diff -u <(env) <(stdbuf env)e não encontrei nenhuma. Mas agora percebo que o que eu deveria ter testado era diff -u <(env) <(stdbuf -oL env).
kasperd
Eu também sou o mesmo tipo de problema. no meu caso, preciso imprimir todas as linhas que contêm 'aaa' e 'bbb'. A primeira solução acima não está funcionando. A segunda solução está funcionando para 'aaa' existir e 'bbb' não existir. ambos existem não funcionando. dando nenhuma saída. meu comando fica assim: tail -f test.txt | stdbuf -oL grep 'aaa' | grep 'bbb' não está dando saída. Podes ajudar-me, por favor.
Sun
18

Normalmente, acho mais útil awkpara esse tipo de verificação lógica:

tail -f /path/to/log | awk '/X/ && !/Y/'
#                           ^^^    ^^^^
#                   this I want    but not this

Testado com duas abas, uma na qual continuo escrevendo seq 20 >> myfilee a outra, por exemplo tail -f myfile | awk '/3/ && !/13/'.

fedorqui
fonte
15

Outra abordagem seria usar uma única grepinvocação em vez de duas e assim evitar o problema de buffer. Basta usar expressões regulares que correspondam a linhas que consistem em 0 ou mais caracteres que não sejam Y, depois um X e, em seguida, 0 ou mais que não Ys até o final da linha "

tail -f /path/to/log | grep '^[^Y]*X[^Y]*$'
Terdon
fonte