Le contexte:
Les utilisateurs me fournissent leurs scripts personnalisés à exécuter. Ces scripts peuvent être de toute sorte comme des scripts pour démarrer plusieurs programmes GUI, des services backend. Je n'ai aucun contrôle sur la façon dont les scripts sont écrits. Ces scripts peuvent être de type bloquant, c'est-à-dire que l'exécution attend que tous les processus enfants (programmes exécutés de manière séquentielle) se terminent
#exaple of blocking script
echo "START"
first_program
second_program
echo "DONE"
ou de type non bloquant, c'est-à-dire ceux qui bifurquent le processus enfant en arrière-plan et sortent quelque chose comme
#example of non-blocking script
echo "START"
first_program &
second_program &
echo "DONE"
Qu'est-ce que j'essaie de réaliser?
Les scripts fournis par l'utilisateur peuvent être de l'un des deux types ci-dessus ou mélanger les deux. Mon travail consiste à exécuter le script et à attendre que tous les processus démarrés par celui-ci se terminent puis à arrêter le nœud. S'il s'agit d'un type de blocage, la casse est simple, c'est-à-dire obtenir le PID du processus d'exécution de script et attendre que ps -ef | grep -ef PID n'ait plus d'entrées. Les scripts non bloquants sont ceux qui me posent problème
Existe-t-il un moyen d'obtenir la liste des PID de tous les processus enfants générés par l'exécution d'un script? Tous les pointeurs ou indices seront très appréciés
pid$(foo.sh; echo $!)
qui vous donnera le PID defoo.sh
sorte que vous puissiez ensuite utiliserps --ppid
. Ça marchera?grep
, justeps –udummy_user
. Regardez également les groupes de processus.ps
sans aucun argument (devrait être uniquementbash
etps
au début). Commencez votre script là-bas. Une fois l'opération terminée, attendez queps | wc -l
la valeur attendue soit atteinte.Réponses:
Pour répondre directement à votre question, la commande
vous donne la liste de tous les processus enfants.
Alternative n ° 1
Mais dans votre cas, il pourrait être plus facile d'utiliser simplement la commande
wait
sans aucun paramètre:Cela attendra la fin de TOUS les processus enfants.
Alternative n ° 2
Une autre alternative consiste à utiliser
$!
pour obtenir le PID du dernier programme et peut-être accumuler dans une variable, comme ceci:puis utilisez wait avec cela (c'est au cas où vous ne voulez attendre qu'un sous-ensemble de vos processus enfants):
Alternative n ° 3
OU, si vous ne voulez attendre que TOUT processus soit terminé, vous pouvez utiliser
Infos bonus
Si vous souhaitez qu'un sigterm de votre script bash ferme également vos processus enfants, vous devrez propager le signal avec quelque chose comme ceci (mettez-le quelque part en haut, avant de démarrer un processus):
la source
Merci les gars pour vos réponses .. J'ai obtenu la solution sur stackoverflow
Vous pouvez utiliser attendre pour attendre la fin de tous les processus d'arrière-plan démarrés par le script utilisateur. Étant donné que l'attente ne fonctionne que sur les enfants du shell actuel, vous devrez source leur script au lieu de l'exécuter en tant que processus distinct.
(script utilisateur source; attendez)
Le sourcing du script dans un sous-shell explicite devrait simuler le démarrage d'un nouveau processus assez étroitement. Sinon, vous pouvez également mettre en arrière-plan le sous-shell, ce qui force le démarrage d'un nouveau processus, puis attendre qu'il se termine.
(script utilisateur source; attendez) & attendez
Voici le lien pour la réponse originale de @chepner: /programming/18663196/how-to-get-list-of-all-child-process-spawned-by-a-script/18663969?noredirect = 1 # 18663969
la source
wait
commande attendra alors les enfants du script utilisateur mais pas ses petits-enfants.