Quelles commandes devrais-je utiliser pour créer deux processus enfants en série?

8

Je veux générer deux processus enfants, mais attendez que le premier atteigne un certain point dans son exécution (qui peut être déterminé en examinant stdout) avant de générer le second. Je ne sais pas quelles commandes unix seraient impliquées pour accomplir cela, et j'ai eu du mal à trouver quoi que ce soit via google en raison de la nature concise et parfois cryptique des noms de commande unix.

Je ne cherche pas une solution au problème spécifique que j'essaie de résoudre (bien que des pointeurs supplémentaires soient appréciés), je me préoccupe principalement de savoir quelles commandes Unix je voudrais rechercher et apprendre à utiliser.

w.brian
la source
Êtes-vous prêt à utiliser Python?
xrisk
3
Sans savoir comment vous déterminez le «certain point de son exécution», c'est très vague.
muru
@muru modifié pour clarifier
w.brian
Vous avez donc réellement besoin de 3 processus. 1. s'exécute, créant une sortie; 2. surveille la sortie de 1 et démarre à un certain point 3. C'est assez d'informations pour vous aider à commencer à faire ce que vous faites. Mais ce n'est pas un bon moyen de concevoir un programme.
djsmiley2kStaysInside

Réponses:

7

Vous pouvez utiliser l' xargsutilitaire pour cela. Il peut exécuter une commande pour chaque ligne sur stdin, il nous suffit donc de nous assurer qu'il xargsobtient en entrée une seule ligne sur stdin au moment où il doit démarrer la commande, ce qui peut être accompli avec grep:

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

Les arguments --max-count=1, --max-lines=1et --no-run-if-emptyassurez-vous qu'il proc2est démarré exactement une fois si et quand proc1sort ${targetString}pour la première fois, et jamais si proc1jamais ne sort ${targetString}. L' --replaceévite qui xargsajoute la ligne d'entrée à sa ligne de commande.

J'ai utilisé la ligne de commande suivante pour le tester:

(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
la source
1
+1 C'est une réponse très créative. Cela deviendrait beaucoup plus compliqué si vous avez besoin du reste de la sortie de proc1. Vous auriez besoin d'utiliser des choses comme tee et des descripteurs de fichiers supplémentaires ou des canaux nommés.
Joe
7

Je ne suis pas sûr qu'il existe une commande / réponse élégante à la question que vous avez posée (c'est-à-dire atteindre un certain point dans son exécution) - mais il existe des outils / techniques qui peuvent être utilisés pour trouver une solution, impliquant probablement plus de 1 des ce qui suit, et peut-être d'autres choses que je ne connais pas encore:

  1. Processus de mise en contexte (&)
  2. Exécution conditionnelle (&& et ||)
  3. dormir
  4. attendre (je m'attends à ce que ce soit particulièrement utile - si vous lancez plus d'un travail en arrière-plan, il attendra que tous les travaux soient terminés)
  5. Canaux nommés (qui pourraient fournir un mécanisme pour parler entre les processus).
  6. inodenotifywait

L'écriture et la vérification des fichiers de verrouillage est également une pratique courante (astuce pro - si vous avez le contrôle de l'environnement, écrivez sur le disque virtuel plutôt que / tmp - sur de nombreuses distributions, il s'agit de / dev / shm).

davidgo
la source
6

Ce n'est qu'une idée, mais demandez au premier processus de diriger sa sortie vers grep. Demandez à grep de diriger sa sortie vers une boucle de ligne de lecture et comparez chaque ligne avec ce que vous recherchez. Une fois trouvé, exécutez proc2.

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

Si "un certain point dans son exécution" peut être déterminé par stdout, qu'en est-il des éléments suivants?

proc1 | grep "stdout trigger string" && proc2

&&devrait se déclencher au grepretour 0, ce qu'il ne fait que lorsqu'il trouve une correspondance.

Louis Waweru
la source
1
grep continuera jusqu'à ce que stdin soit fermé. Il ne retournera rien (0 ou autre) jusque-là.
Bob
@Bob Oh, merci ... Je vais essayer de reformuler cette idée.
Louis Waweru
@bob Ce serait particulièrement compliqué et décousu, et une mauvaise utilisation de l'outil, mais vous pourriez utiliser fail2ban pour surveiller un fichier journal (c'est-à-dire diriger stdout vers un fichier), puis programmer une règle pour exécuter le deuxième script lorsque cette ligne est trouvé (mais je recon modifie un fichier déclencheur et en utilisant inotify est une solution plus élégante)
davidgo
1
Si targetstring se produit plusieurs fois dans la sortie proc1, proc2 sera exécuté plusieurs fois. Si vous le faisiez proc2 &et ensuite break, cela ne se produirait pas, mais cela fermerait le tuyau et ferait se terminer prématurément proc1. Vous pouvez également définir un indicateur une fois que proc2 est démarré et l'utiliser pour vous assurer que proc2 n'est pas exécuté à nouveau. Comme pour l'autre réponse, le reste de la sortie proc1 est ignoré, donc si vous en avez besoin, plus de travail est nécessaire.
Joe
1
@Joe Bon point. La question d'origine était simplement de demander quelles commandes étaient disponibles pour travailler, donc c'est vraiment juste une réponse démontrant le potentiel de ces commandes (principalement |et grepici).
Louis Waweru