Como aplicar um filtro à saída em tempo real de `tail -f`?
60
tail -f path
O exemplo acima produzirá modificações no arquivo instantaneamente, mas eu quero aplicar um filtro à saída, mostrado apenas quando houver uma palavra-chave xxx.
Marcar as respostas como aceitas ajuda outras pessoas que leem suas perguntas e suas respostas a saber qual resposta pode ser mais provável de ajudá-las se tiverem uma pergunta ou problema semelhante. Você pode revisar suas perguntas anteriores clicando no seu nome de usuário.
Dennis Williamson
Respostas:
84
Com o Unix, você pode canalizar a saída de um programa para outro.
Então, para filtrar a cauda, você pode usar o grep:
No entanto, isso tende a ficar aquém. Digamos que você esteja seguindo um arquivo rotacionado com frequência (se for um log de depuração, ele poderá ser rotacionado várias vezes). Nesse caso, tail -Fé seu amigo. Vou deixar você procurar a diferença.
Mas tail -fe tail -Fimprimir um monte de linhas em primeiro lugar, que é muitas vezes indesejável neste caso de uso, portanto, neste caso adicionar-n0
tail -F -n0 somefile | grep somepattern
Tudo bem, até que você queira fazer outra filtragem e tenha cuidado com o buffer. Por padrão, o stdout é buffer de linha ao gravar em um terminal, mas quando totalmente buffer ao gravar em um canal. Portanto, o seguinte emitirá linhas assim que forem encontradas, porque tailé explicitamente armazenado em buffer (ou libera sua saída no final de cada linha) e greptambém é armazenado em buffer porque sua saída está indo para o seu terminal:
tail -F -n0 somefile | grep somepattern
Mas então você decide usar algo como awkou cutprocessar ainda mais a saída.
E agora você se pergunta para onde foi a sua saída ... dependendo do volume de logs, pode achar que obtém saída, mas será uma página de cada vez, porque agora o stdout grepestá operando de maneira totalmente com buffer, e assim awkrecebe 4kB de cada vez (por padrão).
Nesse caso, você pode dizer greppara sempre tornar a linha stdout armazenada em buffer usando a --line-bufferedopção
No entanto, a maioria dos comandos não possui um análogo --line-buffered. No caso de ferramentas com mais scripts, você pode usar uma função para liberar a saída (por exemplo awk, in , a função is fflush(), que compartilha o mesmo nome que seu equivalente em C, ferramentas como Perl e Python têm algo semelhante).
Com pessoas como essa, cutvocê provavelmente está sem sorte; ... mas você pode tentar procurar unbuffer, o que acho que é algo fornecido pela expectcadeia de ferramentas (nunca a usei).
Eu realmente aprecio a explicação de por que isso funciona no modo de buffer de linha. Essa é uma excelente visão, obrigado.
Verde
2
e você pode usar vários pipes e greps e excluir itens com grep -v, obter insensibilidade de maiúsculas e minúsculas com grep -i, etc.
ou seja: tail -100f / var / log / messages | grep -V ACPI | grep -i ata
comece a alinhar 100 linhas a partir do final e mantenha a cauda, primeiro exclua todas as linhas com ACPI, depois mostre linhas com ata, ATA ou qualquer combinação delas.
Outra prática são as opções ABC, para as linhas Depois, Antes e Contexto (linhas antes e depois).
Respostas:
Com o Unix, você pode canalizar a saída de um programa para outro.
Então, para filtrar a cauda, você pode usar o grep:
fonte
Resposta curta:
tail -f somefile | grep somepattern
No entanto, isso tende a ficar aquém. Digamos que você esteja seguindo um arquivo rotacionado com frequência (se for um log de depuração, ele poderá ser rotacionado várias vezes). Nesse caso,
tail -F
é seu amigo. Vou deixar você procurar a diferença.Mas
tail -f
etail -F
imprimir um monte de linhas em primeiro lugar, que é muitas vezes indesejável neste caso de uso, portanto, neste caso adicionar-n0
Tudo bem, até que você queira fazer outra filtragem e tenha cuidado com o buffer. Por padrão, o stdout é buffer de linha ao gravar em um terminal, mas quando totalmente buffer ao gravar em um canal. Portanto, o seguinte emitirá linhas assim que forem encontradas, porque
tail
é explicitamente armazenado em buffer (ou libera sua saída no final de cada linha) egrep
também é armazenado em buffer porque sua saída está indo para o seu terminal:Mas então você decide usar algo como
awk
oucut
processar ainda mais a saída.E agora você se pergunta para onde foi a sua saída ... dependendo do volume de logs, pode achar que obtém saída, mas será uma página de cada vez, porque agora o stdout
grep
está operando de maneira totalmente com buffer, e assimawk
recebe 4kB de cada vez (por padrão).Nesse caso, você pode dizer
grep
para sempre tornar a linha stdout armazenada em buffer usando a--line-buffered
opçãoNo entanto, a maioria dos comandos não possui um análogo
--line-buffered
. No caso de ferramentas com mais scripts, você pode usar uma função para liberar a saída (por exemploawk
, in , a função isfflush()
, que compartilha o mesmo nome que seu equivalente em C, ferramentas como Perl e Python têm algo semelhante).Com pessoas como essa,
cut
você provavelmente está sem sorte; ... mas você pode tentar procurarunbuffer
, o que acho que é algo fornecido pelaexpect
cadeia de ferramentas (nunca a usei).Espero que você tenha achado isso útil.
Cheers, Cameron
fonte
e você pode usar vários pipes e greps e excluir itens com grep -v, obter insensibilidade de maiúsculas e minúsculas com grep -i, etc.
ou seja: tail -100f / var / log / messages | grep -V ACPI | grep -i ata
comece a alinhar 100 linhas a partir do final e mantenha a cauda, primeiro exclua todas as linhas com ACPI, depois mostre linhas com ata, ATA ou qualquer combinação delas.
Outra prática são as opções ABC, para as linhas Depois, Antes e Contexto (linhas antes e depois).
fonte