Ich versuche, ein Shell-Skript so einzurichten, dass Hintergrundprozesse ausgeführt werden. Wenn ich Ctrlcdas Shell-Skript verwende, werden die untergeordneten Elemente beendet und dann beendet.
Das Beste, was mir gelungen ist, ist das hier. Es scheint, dass das kill 0 -INT
Skript vor dem Warten ebenfalls beendet wird, sodass das Shell-Skript abstirbt, bevor die Kinder fertig sind.
Irgendwelche Ideen, wie ich dieses Shell-Skript dazu bringen kann, darauf zu warten, dass die Kinder nach dem Senden sterben INT
?
#!/bin/bash
trap 'killall' INT
killall() {
echo "**** Shutting down... ****"
kill 0 -INT
wait # Why doesn't this wait??
echo DONE
}
process1 &
process2 &
process3 &
cat # wait forever
Antworten:
Ihr
kill
Befehl ist rückwärts.Wie bei vielen UNIX-Befehlen müssen Optionen, die mit einem Minus beginnen, vor anderen Argumenten stehen.
Wenn du schreibst
Es sieht das
-INT
als eine Option und sendetSIGINT
an0
(0
ist eine spezielle Nummer, die alle Prozesse in der aktuellen Prozessgruppe bezeichnet).Aber wenn du schreibst
Es sieht die
0
, entscheidet, dass es keine weiteren Optionen gibt, also verwendet esSIGTERM
standardmäßig. Und sendet das an die aktuelle Prozessgruppe, genauso wie Sie es getan haben(es würde auch versuchen , zu senden
SIGTERM
an-INT
, die einen Syntaxfehler verursachen würde, aber es sendetSIGTERM
an0
ersten und wird nie so weit.)Also Ihr Haupt - Skript ein bekommt ,
SIGTERM
bevor es wird die laufenwait
undecho DONE
.Hinzufügen
an der Spitze gleich danach
und führen Sie es erneut aus, um dies zu beweisen.
Wie Stephane Chazelas betont, werden Ihre Hintergrundkinder (
process1
usw.)SIGINT
standardmäßig ignoriert .In jedem Fall halte ich das Senden
SIGTERM
für sinnvoller.Schließlich bin ich mir nicht sicher, ob
kill -process group
es garantiert ist, zuerst zu den Kindern zu gehen. Das Ignorieren von Signalen beim Herunterfahren ist möglicherweise eine gute Idee.Also versuche folgendes:
quelle
Leider werden Befehle, die im Hintergrund gestartet werden, von der Shell so eingestellt, dass sie SIGINT ignorieren. Schlimmer noch, sie können sie nicht mit ignorieren
trap
. Ansonsten müssten Sie nur nochWeil process1 und process2 den SIGINT erhalten würden, wenn Sie Ctrl-C drücken, da sie Teil derselben Prozessgruppe sind, die die Vordergrundprozessgruppe des Terminals ist.
Der obige Code funktioniert mit pdksh und zsh, die in dieser Hinsicht nicht POSIX-konform sind.
Bei anderen Shells müssten Sie etwas anderes verwenden, um den Standardhandler für SIGINT wiederherzustellen:
oder verwenden Sie ein anderes Signal wie SIGTERM.
quelle
Für diejenigen, die nur einen Prozess beenden und darauf warten möchten, dass er stirbt, aber nicht auf unbestimmte Zeit :
Es wartet maximal 60 Sekunden pro Signaltyp.
Warnung: Diese Antwort hat nichts mit dem Abfangen und Versenden eines Kill-Signals zu tun.
Es wählt die zu tötende App nach Namen oder Argumenten aus. Behalten Sie die Klammern für den ersten Buchstaben des App-Namens bei, um eine Übereinstimmung mit grep selbst zu vermeiden.
Mit einigen Änderungen können Sie direkt die PID oder eine einfachere
pidof process_name
anstelle derps
Anweisung verwenden.Code-Details: Das letzte grep ist, die PID ohne die nachfolgenden Leerzeichen zu erhalten.
quelle
Wenn Sie Hintergrundprozesse verwalten möchten, können Sie die Funktionen zur Bash-Job-Steuerung verwenden.
quelle
Also habe ich auch daran herumgebastelt. In Bash können Sie Funktionen definieren und damit ausgefallene Dinge tun. Meine Kollegen und ich verwenden
terminator
, also erzeugen wir für Stapelausführungen normalerweise eine ganze Reihe von Abschlussfenstern, wenn wir die Ausgabe anzeigen möchten (weniger elegant alstmux
Registerkarten, aber Sie können eine GUI-ähnliche Oberfläche verwenden, haha).Hier ist das Setup, das ich mir ausgedacht habe, sowie ein Beispiel für Dinge, die Sie ausführen können:
Laufen es
Edit @Maxim, habe gerade deinen Vorschlag gesehen, das macht es eine Tonne einfacher! Vielen Dank!
quelle