Estou procurando uma maneira de assistir programaticamente a saída de um comando até que uma determinada string seja observada e depois saia. Isso é muito semelhante a essa pergunta, mas, em vez de ajustar um arquivo, quero 'ajustar' um comando.
Algo como:
assistir -n1 my_cmd | grep -m 1 "String que estou procurando"
(Mas isso não funciona para mim.)
UPDATE: Preciso esclarecer que 'my_cmd' não gera texto continuamente, mas precisa ser chamado repetidamente até que a string seja encontrada (e foi por isso que pensei no comando 'watch'). Nesse aspecto, 'my_cmd' é como muitos outros comandos unix, como: ps, ls, lsof, last, etc.
tail -f
uma saída de programa tão bem quanto um arquivo ... Estou errado?Respostas:
Use um loop:
Em vez de
:
, você pode usarsleep 1
(ou 0.2) para facilitar a CPU.O loop é executado até que o grep encontre a string na saída do comando.
-m 1
significa "uma correspondência é suficiente", ou seja, o grep para de procurar depois de encontrar a primeira correspondência.Você também pode usar o
grep -q
que também fecha após encontrar a primeira correspondência, mas sem imprimir a linha correspondente.fonte
grep -q
que é outra opção. O grep é encerrado após encontrar a string.!
nega o código de saída do pipeline de comandosgrep -m 1
sai quando a string é encontradawatch -e
retorna se algum erro ocorreuMas isso pode ser melhorado para realmente exibir a linha correspondente, que é jogada fora até agora.
fonte
watch
comando (CentOS) não tem a-e
bandeira (o que realmente não deveria importar). Mais importante, porém, quando a string é encontrada, o relógio continua a funcionar e não sai. Parece que quandogrep -m
sai, sai apenas matamy_cmd
, mas nãowatch
.tee
para isso, mas isto introduz uma nova linha enganosa, eu não sei como contornar agora:watch -n1 -e "! date | tee /dev/tty | grep --color -m 1 \"17\""
watch
obedientemente pára de observar quando a string é encontrada, mas na verdade não sai até você pressionar uma tecla. Tão perto.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:
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:
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 direitogrep -m1 "find_me"
- encontre a string de destino&& kill -9 $(cat pid)
- force kill (SIGKILL) otail
processo apósgrep
sair depois de encontrar a string correspondente&& rm pid
- remova o arquivo que criamosfonte
Se
tail
não suportar a+1f
sintaxe, tentetail -f -n +1
. (Ele-n +1
diz para começar do início;tail -f
por padrão, começa com as últimas 10 linhas de saída.)fonte
Anexe o resultado de suas chamadas de programa a um arquivo. Então
tail -f
esse arquivo. Dessa forma, deve funcionar ... espero.Ao reiniciar a chamada para esse programa, você terá que apagar o arquivo ou anexá-lo a alguma coisa, para que não corresponda novamente imediatamente ao que estava procurando.
fonte