Angenommen, wir haben ein Bash-Skript wie folgt:
echo "x" &
echo "y" &
echo "z" &
.....
echo "Z" &
wait
Gibt es eine Möglichkeit, die Exit-Codes der Sub-Shells / Sub-Prozesse zu sammeln? Suchen Sie nach einer Möglichkeit, dies zu tun, und finden Sie nichts. Ich muss diese Subshells parallel betreiben, sonst wäre das ja einfacher.
Ich suche nach einer generischen Lösung (ich habe eine unbekannte / dynamische Anzahl von Unterprozessen, die parallel ausgeführt werden sollen).
bash
shell-script
shell
subshell
Alexander Mills
quelle
quelle
Antworten:
Die Antwort von Alexander Mills, der handleJobs verwendet, gab mir einen guten Ausgangspunkt, gab mir aber auch diesen Fehler
Welches ein heftiges Rennenbedingungsproblem sein kann
Stattdessen habe ich nur pid jedes Kindes gespeichert und gewartet und Exit-Code für jedes Kind speziell abgerufen. Ich finde diesen Cleaner in Bezug auf Unterprozesse, die Unterprozesse in Funktionen erzeugen und das Risiko vermeiden, auf einen übergeordneten Prozess zu warten, bei dem ich auf ein Kind warten wollte. Es ist klarer, was passiert, weil die Falle nicht benutzt wird.
quelle
for job in "${childen[@]}"; do
sollte esfor job in "${1}"; do
aber cool seinchildren_pids+=("$!")
tatsächlich die gewünschte PID für die Sub-Shell erfasst wird.Verwendung
wait
mit einer PID, die :Sie müssen die PID jedes Prozesses währenddessen speichern:
Sie können die Jobsteuerung im Skript auch mit
set -m
einer%n
Jobspezifikation aktivieren und verwenden, möchten dies aber mit ziemlicher Sicherheit nicht. Die Jobsteuerung hat viele andere Nebenwirkungen .wait
Gibt den gleichen Code zurück, mit dem der Vorgang abgeschlossen wurde. Sie könnenwait $X
zu einem beliebigen (angemessenen) späteren Zeitpunkt auf den endgültigen Code zugreifen$?
oder ihn einfach als true / false verwenden:wait
wird angehalten, bis der Befehl abgeschlossen ist, sofern dies noch nicht geschehen ist.Wenn Sie möchten , dass ein Abwürgen vermeiden möchten, können Sie einen Satz
trap
aufSIGCHLD
, zählen die Anzahl der Abschlüsse und behandeln alle diewait
s auf einmal , wenn sie alle fertig sind. Sie können wahrscheinlichwait
fast die ganze Zeit damit davonkommen, allein zu sein.quelle
wait $X
zu einem (angemessenen) späteren Zeitpunkt.Wenn Sie die Befehle gut identifizieren können, können Sie ihren Beendigungscode in eine tmp-Datei drucken und dann auf die gewünschte Datei zugreifen:
Vergessen Sie nicht, die tmp-Dateien zu entfernen.
quelle
Verwenden Sie a
compound command
- setzen Sie die Anweisung in Klammern:wird die Ausgabe geben
Eine andere Art, mehrere Befehle parallel auszuführen, ist die Verwendung von GNU Parallel . Erstellen Sie eine Liste der auszuführenden Befehle und fügen Sie sie in die Datei ein
list
:Führen Sie alle Befehle parallel aus und sammeln Sie die Exit-Codes in der Datei
job.log
:und die Ausgabe ist:
quelle
PIPESTATUS
sollten Sie es überprüfen. Dies gibtseq 10 | gzip -c > seq.gz ; echo ${PIPESTATUS[@]}
zurück0 0
(Exit-Code vom ersten und letzten Befehl).Dies ist das generische Skript, nach dem Sie suchen. Der einzige Nachteil ist, dass Ihre Befehle in Anführungszeichen stehen, was bedeutet, dass das Hervorheben der Syntax über Ihre IDE nicht wirklich funktioniert. Ansonsten habe ich ein paar andere Antworten ausprobiert und dies ist die beste. Diese Antwort enthält die Idee der Verwendung
wait <pid>
von @Michael, geht aber noch einen Schritt weiter und verwendet dentrap
Befehl, der am besten zu funktionieren scheint.danke an @michael homer, der mich auf den richtigen Weg gebracht hat, aber die Verwendung von
trap
befehlen ist der beste Ansatz von AFAICT.quelle
Eine andere Variante der Antwort von @rolf:
Eine andere Möglichkeit, den Exit-Status zu speichern, wäre etwa
und dann habe jedes script
Auf diese Weise erhalten Sie einen eindeutigen Namen für jede Statusdatei, einschließlich des Namens des Skripts, das sie erstellt hat, und der Prozess-ID (falls mehr als eine Instanz desselben Skripts ausgeführt wird), die Sie zur späteren Bezugnahme speichern und in die Datei einfügen können Sie können das gesamte Unterverzeichnis löschen, wenn Sie fertig sind.
Sie können sogar mehr als einen Status von jedem Skript speichern, indem Sie so etwas wie tun
Dadurch wird die Datei wie zuvor erstellt, es wird jedoch eine eindeutige zufällige Zeichenfolge hinzugefügt.
Sie können auch einfach weitere Statusinformationen an dieselbe Datei anhängen.
quelle
script3
wird nur ausgeführt, wennscript1
undscript2
erfolgreich sind undscript1
undscript2
wird parallel ausgeführt:quelle