Kontext:
Benutzer stellen mir ihre benutzerdefinierten Skripte zur Ausführung zur Verfügung. Diese Skripte können beliebig ähnlich sein wie Skripte zum Starten mehrerer GUI-Programme und Backend-Dienste. Ich habe keine Kontrolle darüber, wie die Skripte geschrieben werden. Diese Skripte können blockierend sein, dh die Ausführung wartet, bis alle untergeordneten Prozesse (Programme, die nacheinander ausgeführt werden) beendet werden
#exaple of blocking script
echo "START"
first_program
second_program
echo "DONE"
oder nicht blockierender Typ, dh solche, die untergeordnete Prozesse im Hintergrund abspalten und so etwas wie beenden
#example of non-blocking script
echo "START"
first_program &
second_program &
echo "DONE"
Was versuche ich zu erreichen?
Vom Benutzer bereitgestellte Skripte können von einem der beiden oben genannten Typen oder einer Mischung aus beiden sein. Meine Aufgabe ist es, das Skript auszuführen und zu warten, bis alle von ihm gestarteten Prozesse beendet sind, und dann den Knoten herunterzufahren. Wenn es sich um einen blockierenden Typ handelt, ist der Fall ganz einfach, dh Sie erhalten die PID des Skriptausführungsprozesses und warten, bis ps -ef | grep -ef PID keine Einträge mehr hat. Nicht blockierende Skripte bereiten mir Probleme
Gibt es eine Möglichkeit, eine Liste der PIDs aller untergeordneten Prozesse abzurufen, die durch die Ausführung eines Skripts erzeugt wurden? Alle Hinweise oder Hinweise werden sehr geschätzt
pid$(foo.sh; echo $!)
das Ihnen die PID von gibt,foo.sh
damit Sie sie dann verwenden könnenps --ppid
. Wird es funktionieren?grep
, nurps –udummy_user
. Schauen Sie sich auch Prozessgruppen an.ps
ohne Argumente auflisten (sollte nurbash
undps
am Anfang sein). Starten Sie dort Ihr Skript. Warten Sie danach, bisps | wc -l
der erwartete Wert erreicht ist.Antworten:
Um Ihre Frage direkt zu beantworten, klicken Sie auf den Befehl
gibt Ihnen die Liste aller untergeordneten Prozesse.
Alternative Nr. 1
In Ihrem Fall ist es jedoch möglicherweise einfacher, den Befehl
wait
ohne Parameter zu verwenden:Dies wartet, bis ALLE untergeordneten Prozesse abgeschlossen sind.
Alternative Nr. 2
Eine andere Alternative besteht
$!
darin, die PID des letzten Programms abzurufen und möglicherweise in einer Variablen zu akkumulieren, wie folgt :und verwenden Sie dann wait damit (dies ist der Fall, wenn Sie nur auf eine Teilmenge Ihrer untergeordneten Prozesse warten möchten):
Alternative Nr. 3
Oder, wenn Sie nur warten, bis ANY Prozess abgeschlossen ist, können Sie
Bonusinfo
Wenn Sie möchten, dass ein Sigterm in Ihrem Bash-Skript auch Ihre untergeordneten Prozesse schließt, müssen Sie das Signal mit so etwas weitergeben (setzen Sie dies irgendwo oben, bevor Sie einen Prozess starten):
quelle
Vielen Dank für Ihre Antworten. Ich habe die Lösung für Stackoverflow erhalten
Mit wait können Sie warten, bis alle von Userscript gestarteten Hintergrundprozesse abgeschlossen sind. Da wait nur für untergeordnete Elemente der aktuellen Shell funktioniert, müssen Sie deren Skript als Quellcode ausführen, anstatt es als separaten Prozess auszuführen.
(Quellbenutzerskript; warten)
Die Beschaffung des Skripts in einer expliziten Unterschale sollte das Starten eines neuen Prozesses genau genug simulieren. Wenn nicht, können Sie auch die Unterschale im Hintergrund speichern, wodurch ein neuer Prozess gestartet wird, und dann warten, bis er abgeschlossen ist.
(Quellbenutzerskript; warten) & warten
Hier ist der Link für die ursprüngliche Antwort von @chepner: /programming/18663196/how-to-get-list-of-all-child-process-spawned-by-a-script/18663969?noredirect = 1 # 18663969
quelle
wait
Befehl wartet dann auf die Kinder von Userscript , nicht jedoch auf seine Enkelkinder.