Para aqueles que têm um programa que está gravando continuamente no stdout, tudo o que você precisa fazer é canalizá-lo para grep com a opção 'correspondência única'. Quando o grep encontrar a string correspondente, ele sairá, o que fecha o stdout no processo que está sendo canalizado para o grep. Esse evento naturalmente deve fazer com que o programa saia normalmente desde que o processo seja gravado novamente .
O que acontecerá é que o processo receberá um SIGPIPE quando tentar gravar no stdout fechado após a saída do grep. Aqui está um exemplo com o ping, que seria executado indefinidamente:
$ ping superuser.com | grep -m 1 "icmp_seq"
Este comando corresponderá ao primeiro 'pong' bem-sucedido e, em seguida, sairá da próxima vez que ping
tentar gravar no stdout.
Contudo,
Nem sempre é garantido que o processo seja gravado no stdout novamente e, portanto, pode não causar o aumento de um SIGPIPE (por exemplo, isso pode acontecer ao seguir um arquivo de log). A melhor solução que consegui encontrar para esse cenário envolve a gravação em um arquivo; comente se você acha que pode melhorar:
$ { tail -f log_file & echo $! > pid; } | { grep -m1 "find_me" && kill -9 $(cat pid) && rm pid; }
Quebrando isso:
tail -f log_file & echo $! > pid
- segue um arquivo, anexa o processo ao plano de fundo e salva o PID ( $!
) em um arquivo. Tentei exportar o PID para uma variável, mas parece que há uma condição de corrida entre aqui e quando o PID é usado novamente.
{ ... ;}
- agrupe esses comandos para que possamos canalizar a saída para grep, mantendo o contexto atual (ajuda ao salvar e reutilizar variáveis, mas não foi capaz de fazer essa parte funcionar)
|
- canalize o stdout do lado esquerdo para o stdin do lado direito
grep -m1 "find_me"
- encontre a string de destino
&& kill -9 $(cat pid)
- force kill (SIGKILL) o tail
processo após grep
sair depois de encontrar a string correspondente
&& rm pid
- remova o arquivo que criamos
tail -f
uma saída de programa tão bem quanto um arquivo ... Estou errado?