“Observe” a saída de um comando até que uma determinada sequência seja observada e saia


29

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.


Eu teria pensado que era possível tail -fuma saída de programa tão bem quanto um arquivo ... Estou errado?
— Joanis

@Joanis. Você está certo, mas no meu caso 'my_cmd' não continuamente produzir saída e deve ser repetidamente chamado (muito parecido com a maioria dos comandos: ps, ls, lsof, etc.)
— gdw2

Respostas:


41

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 1significa "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 -qque também fecha após encontrar a primeira correspondência, mas sem imprimir a linha correspondente.


uma explicação desse comando seria apreciada.
— Mark W

@ MarkW: Atualizado.
— choroba

alguém mencionou grep -qque é outra opção. O grep é encerrado após encontrar a string.
— Dom

observe que esse comando executará repetidamente o comando em questão, o que pode ou não ser desejável.
— adrien 12/06

1
@A__: É desejável, conforme declarado no OP em "Atualização".
— choroba 12/06

11
watch -e "! my_cmd | grep -m 1 \"String Im Looking For\""
  • ! nega o código de saída do pipeline de comandos
  • grep -m 1 sai quando a string é encontrada
  • watch -e retorna se algum erro ocorreu

Mas isso pode ser melhorado para realmente exibir a linha correspondente, que é jogada fora até agora.


Obrigado pela explicação detalhada, mas não funciona para mim. Meu watchcomando (CentOS) não tem a -ebandeira (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 quando grep -msai, sai apenas mata my_cmd, mas não watch.
— Gdw2

Não, isso importa !, o sinalizador "-e" serve para deixar o relógio quando o comando tem um código de erro diferente de 0. Como o relógio não está presente, está prestes a continuar na sua plataforma. De qualquer forma, é bom saber que na minha instalação do Ubuntu 11.10 está tudo bem. Às vezes, também tenho problemas com o Mac OSX em relação a ferramentas de linha de comando muito desatualizadas e estou usando portas mac até agora para obter um software mais atual.
— math

Isso interrompe se o padrão for encontrado, mas não mostrará nenhuma saída, até que isso aconteça
— Mark

Você pode empregar teepara 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\""
— matemática

Sim, isso não funcionou para mim. watchobedientemente pára de observar quando a string é encontrada, mas na verdade não sai até você pressionar uma tecla. Tão perto.
— Mlissner

8

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 pingtentar 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:

  1. 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.
  2. { ... ;}- 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)
  3. | - canalize 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)- force kill (SIGKILL) o tailprocesso após grep sair depois de encontrar a string correspondente
  6. && rm pid - remova o arquivo que criamos

0
my_cmd | tail +1f | sed '/String Im Looking For/q'

Se tailnão suportar a +1fsintaxe, tente tail -f -n +1. (Ele -n +1diz para começar do início; tail -fpor padrão, começa com as últimas 10 linhas de saída.)


Por favor, veja minha atualização para a pergunta.
— Gdw2

0

Anexe o resultado de suas chamadas de programa a um arquivo. Então tail -fesse 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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.