Quais comandos eu usaria para criar dois processos filhos em série?

8

Eu quero gerar dois processos filhos, mas aguarde até que o primeiro atinja um certo ponto em sua execução (que pode ser determinado pelo exame de stdout) antes de gerar o segundo. Não tenho certeza de quais comandos unix estariam envolvidos nessa tarefa e tive dificuldade em encontrar algo via google devido à natureza concisa e às vezes enigmática dos nomes de comando unix.

Não estou procurando uma solução para o problema específico que estou tentando resolver (embora qualquer ponteiro adicional seja apreciado), estou principalmente preocupado em saber quais comandos unix eu gostaria de procurar e aprender a usar.

w.brian
fonte
Você está aberto a usar Python?
xrisk
3
Sem saber como você determina o "certo ponto de sua execução", isso é muito vago.
Muni
@muru editado para esclarecer
w.brian
Então você realmente precisa de 3 processos. 1. corre, criando saída; 2. monitora a saída de 1 e, em um determinado momento, inicia 3. Isso é informação suficiente para você começar a fazer o que estiver fazendo. Mas não é uma boa maneira de projetar um programa.
djsmiley2kStaysInside

Respostas:

7

Você pode usar o xargsutilitário para isso. Ele pode executar um comando para cada linha no stdin, portanto, apenas precisamos garantir que xargsreceba como entrada uma única linha no stdin no momento em que deve iniciar o comando, o que pode ser realizado com grep:

proc1 | grep --max-count=1 "${targetString}" | xargs --max-lines=1 --no-run-if-empty --replace -- proc2

Os argumentos --max-count=1, --max-lines=1e --no-run-if-emptygarantir que proc2é iniciado exatamente uma vez, se e quando proc1saídas ${targetString}, pela primeira vez, e nunca se proc1nunca saídas ${targetString}. Os --replaceevita que xargsacrescenta o linha de entrada para sua linha de comando.

Eu usei a seguinte linha de comando para testá-lo:

(echo Start >&2; sleep 3 ; echo Trigger; sleep 3; echo End >&2) | grep --max-count=1 Trigger | xargs --max-lines=1 --no-run-if-empty --replace -- echo "Triggered"
Philipp Wendler
fonte
11
+1 Esta é uma resposta muito criativa. Seria consideravelmente mais complicado se você precisar do restante da saída do proc1. Você precisaria usar coisas como tee e descritores de arquivos adicionais ou pipes nomeados.
2120 Joe
7

Não tenho certeza de que exista um comando / resposta elegante para a pergunta que você fez (por exemplo, alcance um certo ponto em sua execução) - mas existem ferramentas / técnicas que podem ser usadas para apresentar uma solução, provavelmente envolvendo mais de 1 o seguinte, e talvez outras coisas que ainda não sei:

  1. Processos em background (&)
  2. Execução condicional (&& e ||)
  3. dormir
  4. wait (espero que isso seja particularmente útil - se você iniciar mais de 1 trabalho em segundo plano, ele aguardará até que todos os trabalhos sejam concluídos)
  5. Canais nomeados (que poderiam fornecer um mecanismo para conversar entre processos).
  6. inodenotifywait

Escrever e verificar arquivos de bloqueio também é uma prática comum (dica profissional - se você tiver controle do ambiente, escreva no ramdisk em vez de / tmp - em muitas distros, isso é / dev / shm).

davidgo
fonte
6

Isso é apenas uma idéia, mas faça com que o primeiro processo canalize sua saída para grep. Faça com que o grep envie sua saída para um loop de linha de leitura e compare cada linha com o que você está procurando. Uma vez encontrado, execute proc2.

#!/bin/bash
targetString="line you are looking for"
proc1 | grep "${targetString}" |
while read line
do
if [ "$line" = "${targetString}" ]; then
    proc2
fi
done

Se "um certo ponto de sua execução" pode ser determinado por stdout, e quanto a seguir?

proc1 | grep "stdout trigger string" && proc2

&&deve disparar quando grepretorna 0, o que ocorre somente quando encontra uma correspondência.

Louis Waweru
fonte
11
O grep continuará até o stdin ser fechado. Não retornará nada (0 ou não) até então.
Bob
@ Bob Oh, obrigado ... Vou tentar reformular essa idéia.
Louis Waweru
@bob Seria particularmente confuso e desarticulado, e um uso indevido da ferramenta, mas você poderia usar o fail2ban para monitorar um arquivo de log (por exemplo, pipe stdout para um arquivo) e depois programar uma regra para executar o segundo script quando essa linha estiver encontrado (mas Recon modificar um ficheiro de gatilho e usando inotify é uma solução mais elegante)
davidgo
11
Se a cadeia de destino ocorrer mais de uma vez na saída proc1, proc2 será executado várias vezes. Se você fizesse proc2 &isso break, isso não aconteceria, mas fecharia o canal e faria com que proc1 terminasse prematuramente. Como alternativa, você pode definir um sinalizador assim que o proc2 for iniciado e usá-lo para garantir que o proc2 não seja executado novamente. Como na outra resposta, o restante da saída proc1 é descartado; portanto, se você precisar, mais trabalho será necessário.
21418 Joe
11
@ Joe Bom ponto. A pergunta original estava na verdade apenas perguntando sobre quais comandos estavam disponíveis para trabalhar, portanto, essa é realmente apenas uma resposta que demonstra o potencial de alguns desses comandos (principalmente |e grepaqui).
Louis Waweru 22/02