Ich habe ein einfaches Bash-Skript, das zwei Server startet:
#!/bin/bash
(cd ./frontend && gulp serve) & (cd ./backend && gulp serve --verbose)
Wenn der zweite Befehl beendet wird, scheint der erste Befehl weiterhin ausgeführt zu werden.
Wie kann ich dies ändern, damit der andere Befehl beendet wird, wenn einer der Befehle beendet wird?
Beachten Sie, dass die Fehlerstufen der Hintergrundprozesse nicht überprüft werden müssen, sondern nur, ob sie beendet wurden.
bash
shell-script
background-process
blah238
quelle
quelle
gulp ./fronend/serve && gulp ./backend/serve --verbose
?serve
Ist ein Argument, keine Datei, daher muss das aktuelle Verzeichnis festgelegt werden.Antworten:
Dies startet beide Prozesse, wartet auf den ersten, der beendet wird und beendet dann den anderen:
Wie es funktioniert
Start:
Die beiden obigen Befehle starten beide Prozesse im Hintergrund.
Warten
Dies wartet darauf, dass einer der Hintergrundjobs beendet wird.
Aufgrund der
-n
Option ist hierfür mindestens Bash 4.3 erforderlich.Töten
Dadurch werden alle Jobs beendet, bei denen der aktuelle Prozess der übergeordnete Prozess ist. Mit anderen Worten, dies beendet jeden Hintergrundprozess, der noch ausgeführt wird.
Wenn Ihr System nicht über
pkill
Folgendes verfügt, ersetzen Sie diese Zeile durch:die auch tötet die aktuelle Prozessgruppe .
Leicht testbares Beispiel
Indem wir das Skript ändern, können wir es auch ohne
gulp
Installation testen :Das obige Skript kann ausgeführt werden als
bash script.sh 1 3
und der erste Prozess wird zuerst beendet. Alternativ kann man es als ausführenbash script.sh 3 1
und der zweite Prozess wird zuerst beendet. In beiden Fällen kann man sehen, dass dies wie gewünscht funktioniert.quelle
bash
unterstützen die-n
Option zumwait
Befehl. (2) Ich stimme dem ersten Satz zu 100% zu - Ihre Lösung startet zwei Prozesse, wartet, bis der erste beendet ist, und tötet dann den anderen. Aber die Frage lautet: "... wenn einer der Befehle fehlerfrei ist, wird der andere beendet?" Ich glaube, dass Ihre Lösung nicht den Anforderungen des OP entspricht. (3) Warum hast du gewechselt(…) &
zu{ …; } &
? Die&
Kräfte der Liste (Gruppenkommando) ohnehin in einer Subshell auszuführen. IMHO, Sie haben Zeichen hinzugefügt und möglicherweise Verwirrung (ich musste es zweimal anschauen, um es zu verstehen) ohne Nutzen eingeführt.pkill
ist für mich nicht verfügbar,kill 0
scheint aber den gleichen Effekt zu haben. Außerdem habe ich meine Git für Windows-Umgebung aktualisiert und es sieht so aus, als ob eswait -n
jetzt funktioniert. Daher akzeptiere ich diese Antwort.kill
. Die Dokumentation auf meinem System erwähnt es nicht. Funktioniert aberkill 0
trotzdem. Guter Fund!Das ist knifflig. Folgendes habe ich mir ausgedacht: es ist möglicherweise möglich, es zu vereinfachen / zu rationalisieren:
while true; do sleep 42; done &
), der für immer schläft / pausiert. Wenn Sie sicher sind, dass Ihre beiden Befehle innerhalb einer bestimmten Zeitspanne (z. B. einer Stunde) beendet werden, können Sie dies in einen einzelnen Ruhezustand ändern, der diese Zeitspanne überschreitet (zsleep 3600
. B. ). Sie können dann die folgende Logik ändern, um diese als Zeitüberschreitung zu verwenden. dh, beenden Sie die Prozesse, wenn sie nach dieser Zeit noch ausgeführt werden. (Beachten Sie, dass das obige Skript dies derzeit nicht tut.)./
fürcd
.command & echo "$!" > somewhere; wait "$!"
ist ein kniffliges Konstrukt, das einen Prozess asynchron startet, seine PID erfasst und dann darauf wartet. es zu einer Art (synchronem) Vordergrundprozess machen. Dies geschieht jedoch innerhalb einer(…)
Liste, die sich vollständig im Hintergrund befindet, sodass diegulp
Prozesse asynchron ablaufen.gulp
Schreiben Sie nach dem Beenden eines der Prozesse seinen Status in eine temporäre Datei und beenden Sie den Prozess "Für immer schlafen".sleep 1
Zum Schutz vor einer Race-Bedingung, bei der der erste Hintergrundprozess abbricht, bevor der zweite die Möglichkeit erhält, seine PID in die Datei zu schreiben.gulp
Prozesse beendet wird , wie oben angegeben.quelle
Der Vollständigkeit halber habe ich Folgendes verwendet:
Dies funktioniert für mich unter Git für Windows 2.5.3 64-Bit. Ältere Versionen akzeptieren die
-n
Option möglicherweise nichtwait
.quelle
Auf meinem System (Centos)
wait
habe-n
ich Folgendes getan:Dies wartet nicht auf "entweder", sondern auf den ersten. Dennoch kann es hilfreich sein, wenn Sie wissen, welcher Server zuerst gestoppt wird.
quelle
wait
die-n
Option verfügbar ist oder nicht, hängt von der verwendeten Shell ab, nicht von der Linux-Distribution.