Como aplicar um filtro à saída em tempo real de 'tail -f'?

51
tail -f path

O texto acima irá gerar modificações no arquivo instantaneamente, mas eu quero aplicar um filtro na saída, mostrar apenas quando houver uma palavra-chave xxx nela.

Como abordar isso?

    
por wamp 05.07.2010 / 11:13

3 respostas

69

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:

tail -f path | grep your-search-filter
    
por 05.07.2010 / 11:17
12

Resposta curta: tail -f somefile | grep somepattern

No entanto, isso tende a ficar aquém. Digamos que você esteja seguindo um arquivo que é rotacionado com frequência (se for um log de depuração, ele pode ser rotacionado várias vezes). Nesse caso, tail -F é seu amigo. Eu vou deixar você olhar a diferença.

Mas tail -f e tail -F imprimem um monte de linhas primeiro, o que geralmente é indesejável neste caso de uso, então, neste caso, adicione -n0

tail -F -n0 somefile | grep somepattern

Isso vai ficar bem, até você querer fazer alguma outra filtragem, e então você precisa tomar cuidado com o armazenamento em buffer. O stdout é armazenado em buffer por padrão ao gravar em um terminal , mas quando totalmente armazenado em buffer ao gravar em um pipe. Então, o seguinte irá emitir linhas assim que forem encontradas, porque tail é explicitamente line-buffered (ou libera sua saída no final de cada linha), e grep também é buffer de linha porque sua saída está indo para o seu terminal:

tail -F -n0 somefile | grep somepattern

Mas você decide usar algo como awk ou cut para processar ainda mais a saída.

tail -F -n0 somefile | grep somepattern | awk '{print $3}'

E agora você se pergunta para onde sua saída foi ... dependendo do volume de logs, você pode achar que obtém a saída, mas será uma página de cada vez, porque agora o stdout de grep está em operação de forma totalmente em buffer, e assim awk recebe a entrada 4kB de cada vez (por padrão).

Nesse caso, você pode dizer a grep para sempre fazer o buffer de linhas stdout usando a opção --line-buffered .

tail -F -n0 somefile | grep --line-buffered somepattern | ...

No entanto, a maioria dos comandos não possui um análogo de --line-buffered . No caso de ferramentas mais scriptáveis, você pode usar uma função para liberar a saída (por exemplo, em awk , a função é fflush() , que compartilha o mesmo nome da sua contraparte C, ferramentas como Perl e Python têm algo semelhante ).

Com os gostos de cut , você provavelmente está sem sorte; ... mas você pode tentar procurar por unbuffer , que é algo que eu acho que é fornecido pelo expect toolchain (nunca usei isso).

Espero que você tenha achado isso útil.

Felicidades, Cameron

    
por 02.08.2016 / 12:46
2

e você pode usar vários pipes e greps, e excluir coisas com grep -v, insensibilidade a maiúsculas e minúsculas com grep -i, etc.

ou seja: tail -100f / var / log / messages | grep -V ACPI | grep -i ata

comece a seguir 100 linhas a partir do final, e continue seguindo, primeiro exclua todas as linhas com ACPI, então mostre as linhas com ata, ATA, ou qualquer mistura delas.

Outra prática é as opções ABC, para as linhas After, Before e Context (linhas antes e depois).

    
por 05.07.2010 / 22:12