¿Qué comandos usaría para crear dos procesos secundarios en serie?

8

Quiero generar dos procesos secundarios, pero espere hasta que el primero alcance un cierto punto en su ejecución (que puede determinarse examinando stdout) antes de generar el segundo. No estoy seguro de qué comandos de Unix estarían involucrados en lograr esto, y he tenido dificultades para encontrar algo a través de Google debido a la naturaleza concisa ya veces críptica de los nombres de comandos de Unix.

No estoy buscando una solución para el problema específico que estoy tratando de resolver (aunque agradecería cualquier puntero adicional), me preocupa principalmente saber qué comandos de Unix me gustaría buscar y aprender a usar.

w.brian
fuente
¿Estás abierto a usar Python?
xrisk
3
Sin saber cómo se determina el "cierto punto en su ejecución", esto es muy vago.
muru
@muru editado para aclarar
w.brian
Entonces realmente necesitas 3 procesos. 1. corre, creando salida; 2. monitorea la salida de 1, y en cierto punto comienza 3. Esta es suficiente información para que comiences a hacer lo que sea que estés haciendo. Pero no es una buena forma de diseñar un programa.
djsmiley2kStaysInside

Respuestas:

7

Puede usar la xargsutilidad para esto. Puede ejecutar un comando para cada línea en stdin, por lo que solo debemos asegurarnos de que xargsobtenga como entrada una sola línea en stdin en el momento en que debe iniciar el comando, lo que se puede lograr con grep:

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

Los argumentos --max-count=1, --max-lines=1y --no-run-if-emptyasegúrese de que proc2se inicie exactamente una vez si y cuando proc1sale ${targetString}por primera vez, y nunca si proc1nunca sale ${targetString}. El --replaceevita que xargsagrega la línea de entrada a su línea de comando.

Usé la siguiente línea de comando para probarlo:

(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
fuente
1
+1 Esta es una respuesta muy creativa. Sin embargo, se volvería considerablemente más complicado si necesita el resto de la salida de proc1. Tendría que usar cosas como tee y descriptores de archivos adicionales o canalizaciones con nombre.
Joe
7

No estoy seguro de que haya una orden / respuesta elegante a la pregunta que hizo (es decir, llegar a un cierto punto en su ejecución), pero hay herramientas / técnicas que se pueden utilizar para encontrar una solución, que probablemente implique más de 1 de lo siguiente, y quizás otras cosas que aún no conozco:

  1. Procesos de fondo (&)
  2. Ejecución condicional (&& y ||)
  3. dormir
  4. esperar (espero que esto sea particularmente útil: si inicia más de 1 trabajo en segundo plano, esperará hasta que se completen todos los trabajos)
  5. Tuberías con nombre (que podrían proporcionar un mecanismo para hablar entre procesos).
  6. inodenotifywait

Escribir y verificar archivos de bloqueo también es una práctica común (consejo profesional: si tiene control del entorno, escriba en el disco RAM en lugar de / tmp, en muchas distribuciones esto es / dev / shm).

davidgo
fuente
6

Esto es solo una idea, pero haga que el primer proceso canalice su salida a grep. Haga que grep canalice su salida a un bucle de línea de lectura y compare cada línea con lo que está buscando. Una vez encontrado, ejecute proc2.

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

Si se puede determinar "cierto punto en su ejecución" stdout, entonces, ¿qué tal lo siguiente?

proc1 | grep "stdout trigger string" && proc2

&&debería disparar cuando grepregrese 0, lo que solo hace cuando encuentra una coincidencia.

Louis Waweru
fuente
1
grep continuará hasta que se cierre stdin. No devolverá nada (0 o de otro modo) hasta entonces.
Bob
@Bob Oh, gracias ... Trataré de reformular esta idea.
Louis Waweru
@bob Sería particularmente desordenado y desarticulado, y un mal uso de la herramienta, pero podría usar fail2ban para monitorear un archivo de registro (es decir, canalizar stdout a un archivo), y luego programar una regla para ejecutar el segundo script cuando esa línea es encontrado (pero reconozco que modificar un archivo de activación y usar inotify es una solución más elegante)
davidgo
1
Si la cadena de destino ocurre más de una vez en la salida proc1, proc2 se ejecutará varias veces. Si lo hiciera proc2 &y entonces break, eso no sucedería, pero eso cerraría la tubería y haría que el proceso terminara prematuramente. Alternativamente, puede establecer un indicador una vez que se inicie proc2 y usarlo para asegurarse de que proc2 no se ejecute nuevamente. Al igual que con la otra respuesta, el resto de la salida proc1 se descarta, por lo que si lo necesita, se necesita más trabajo.
Joe
1
@ Joe Buen punto. La pregunta original en realidad era solo preguntar qué comandos estaban disponibles para trabajar, por lo que esta es realmente una respuesta que demuestra el potencial de algunos de esos comandos (principalmente |y grepaquí).
Louis Waweru