“observe” a saída de um comando até que uma sequência específica seja observada e, em seguida, saia

20

Estou procurando uma maneira de assistir programaticamente a saída de um comando até que uma determinada string seja observada e, em seguida, saia. Isso é muito parecido com esta pergunta, mas em vez de rejeitar um arquivo, eu quero 'tail' um comando.

Algo como:

watch -n1 my_cmd | grep -m 1 "String Im Looking For"

(Mas isso não funciona para mim.)

UPDATE: Eu preciso esclarecer que 'my_cmd' não produz texto continuamente, mas precisa ser repetidamente chamado até que a string seja encontrada (é por isso que pensei no comando 'watch'). A este respeito, 'my_cmd' é como muitos outros comandos unix como: ps, ls, lsof, last, etc.

    
por gdw2 06.01.2012 / 01:30

5 respostas

27

Use um loop:

until my_cmd | grep -m 1 "String Im Looking For"; do : ; done

Em vez de : , você pode usar sleep 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 que "uma correspondência é suficiente", ou seja, o grep pára de pesquisar depois de encontrar a primeira correspondência.

    
por 06.01.2012 / 10:03
7
watch -e "! my_cmd | grep -m 1 \"String Im Looking For\""
  • ! nega o código de saída do pipeline de comando
  • grep -m 1 sai quando a string é encontrada
  • watch -e retorna se algum erro ocorreu

Mas isso pode ser melhorado para exibir a linha correspondente, que foi descartada até agora.

    
por 06.01.2012 / 11:49
4

Para aqueles que têm um programa que está continuamente escrevendo para stdout, tudo que você precisa fazer é canalizá-lo para grep com a opção 'single match'. Uma vez que o grep encontre a string correspondente, ele sairá, o que fecha o stdout no processo que está sendo canalizado para o grep. Este evento deve naturalmente 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 em stdout fechado após o grep ter saído. Aqui está um exemplo com o ping, que, de outra forma, seria executado indefinidamente:

$ ping superuser.com | grep -m 1 "icmp_seq"

Este comando irá coincidir com o primeiro 'pong' bem-sucedido e, em seguida, sairá da próxima vez que ping tentar escrever para stdout.

No entanto,

Nem sempre é garantido que o processo irá gravar no stdout novamente e, portanto, pode não fazer com que um SIGPIPE seja gerado (por exemplo, isso pode acontecer ao rastrear um arquivo de log). A melhor solução que consegui criar para esse cenário envolve gravar em um arquivo; por favor, 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:

  1. tail -f log_file & echo $! > pid - coroa um arquivo, anexa o processo ao segundo plano e salva o PID ( $! ) em um arquivo. Eu 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.
  2. { ... ;} - agrupe estes comandos juntos para que possamos canalizar a saída para grep mantendo o contexto atual (ajuda ao salvar e reutilizar variáveis, mas não conseguiu fazer com que a parte funcione)
  3. | - canaliza o stdout do lado esquerdo para o stdin do lado direito
  4. grep -m1 "find_me" - encontre a string de destino
  5. && kill -9 $(cat pid) - forçar kill (SIGKILL) o tail process após grep sair assim que encontrar a string correspondente
  6. && rm pid - remova o arquivo que criamos
por 12.03.2018 / 22:06
0
my_cmd | tail +1f | sed '/String Im Looking For/q'

Se tail não suportar a sintaxe +1f , tente tail -f -n +1 . (O -n +1 diz para iniciar no início; tail -f por padrão começa com as últimas 10 linhas de saída.)

    
por 06.01.2012 / 03:01
0

Anexe o resultado de suas chamadas de programa a um arquivo. Então tail -f desse arquivo. Dessa forma, deve funcionar ... espero.

Quando você reiniciar a chamada para esse programa, terá que apagar o arquivo ou acrescentar alguns detalhes para que ele não corresponda novamente ao que estava procurando.

    
por 06.01.2012 / 05:24

Tags