Einen Bash-Befehl nach einigen gleichzeitigen Befehlen ausführen?


13

Ich möchte einige Befehle parallel ausführen. Wenn alle diese Befehle beendet sind, starten Sie den nächsten. Ich denke, der folgende Ansatz wird funktionieren

#!/bin/bash
command1 &
command2 &
command3 &&
command4

aber das tat es nicht. Ich muss ausgeführt werden, command4wenn alle ersten drei Befehle vollständig ausgeführt wurden.

Antworten:


28
#!/bin/bash
command1 &
command2 &
command3 &

wait
command4

wait (ohne Argumente) wird warten, bis alle Prozesse im Hintergrund beendet wurden.

Die vollständige Beschreibung waitim bashHandbuch:

wait [-n] [n ...]

Warten Sie auf jeden angegebenen untergeordneten Prozess und geben Sie seinen Beendigungsstatus zurück. Jedes nkann eine Prozess-ID oder eine Auftragsspezifikation sein. Wird eine Jobspezifikation angegeben, wird auf alle Prozesse in der Pipeline dieses Jobs gewartet. Wenn nnicht angegeben, wird auf alle derzeit aktiven untergeordneten Prozesse gewartet, und der Rückgabestatus ist Null. Wenn die -nOption angegeben ist, wird darauf waitgewartet, dass ein Auftrag beendet wird, und der Beendigungsstatus wird zurückgegeben. Wenn nein nicht vorhandener Prozess oder Job angegeben ist, lautet der Rückgabestatus 127. Andernfalls ist der Rückgabestatus der Beendigungsstatus des letzten Prozesses oder Jobs, auf den gewartet wurde.


1
Eine andere Möglichkeit ist, die PID jedes Kindes mit etwas wie zu speichern PID1=$!und dann auf alle mit zu warten wait "$PID1" "$PID2" "$PID3". Das ist etwas komplizierter, funktioniert aber, wenn der Prozess andere Kinder hat, auf die Sie nicht warten möchten.
Kasperd

1
@kasperd Besser mit einem Array in diesem Fall: cmd1 & pids=( $! ); cmd2 & pids+=( $! ); cmd3 & pids+=( $! ); wait "${pids[@]}"oder so ähnlich.
Kusalananda

@kasperd Mit "besser" meine ich "benutze nur eine Variable". An sich nichts falsches daran, viele zu verwenden, und wahrscheinlich ist es für kleine Fälle wie diesen völlig in Ordnung.
Kusalananda

0

Ich mag die waitAntwort, aber nur als akademische Übung denke ich, dass dies auch funktionieren würde:

bash -c 'command1 & command2 & command3 &' && command4

Bitte korrigieren Sie mich, wenn ich falsch liege.


2
Hast du das getestet? Es funktioniert absolut nicht. Beispiel: time bash -c "sleep 5 &sleep 5 &sleep 5 &" && echo foo Wenn nicht angegeben wird, dass der Befehl bash fünf Sekunden gedauert hat, hat er nicht das getan, was Sie wollen.
Seth Robertson

Ich habe es mit Schlaf und Echos getestet und es schien zu funktionieren. Ihr Beispiel beweist das Gegenteil.
Burger
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.