Neue Antwort:
Diese Frage ist viel interessanter, als ich ursprünglich vermutet hatte. Die Antwort wird im Wesentlichen hier gegeben:
Was passiert mit einem SIGINT (^C), wenn es an ein Perl-Skript gesendet wird, das Kinder enthält?
Hier ist der relevante Leckerbissen. Mir ist klar, dass Sie Perl nicht verwenden, aber ich gehe davon aus, dass Bash die Konvention von C verwendet.
Die eingebaute Systemfunktion von Perl funktioniert in Bezug auf Signale genauso wie die C-Funktion system(3) aus der Standard-C-Bibliothek. Wenn Sie die Perl-Version von system() oder Pipe open oder Backticks verwenden, dann ist das übergeordnete System das eine aufrufende System anstelle des byit genannten - wird jedes SIGINT und SIGQUIT IGNORIEREN, während die Kinder laufen.
Diese Erklärung ist die beste, die ich über die verschiedenen Auswahlmöglichkeiten gesehen habe. Es sagt auch, dass Bash den WCE-Ansatz macht. Das heißt, wenn ein übergeordneter Prozess SIGINT empfängt, wartet er, bis sein untergeordneter Prozess zurückkehrt. Wenn dieser behandelte Prozess von einem SIGINT beendet wurde, wird er auch mit SIGINT beendet. Wenn das Kind auf andere Weise ausgetreten ist, ignoriert es SIGINT.
Es gibt auch eine Möglichkeit, mit der die aufrufende Shell feststellen kann, ob das aufgerufene Programm bei SIGINT beendet wurde und ob es SIGINT ignoriert (oder es für andere Zwecke verwendet hat). Wie bei WUE wartet die Shell darauf, dass das Kind fertig ist. Es stellt fest, ob das Programm auf SIGINT beendet wurde und wenn ja, bricht es das Skript ab. Wenn das Programm einen anderen Ausgang hat, wird das Skript fortgesetzt. Ich werde die Vorgehensweise für den Rest dieses Dokuments "WCE" (für "Warten und kooperativer Ausgang") nennen.
Ich kann auf der Bash-Manpage keinen Verweis darauf finden, aber ich werde weiter in den Info-Dokumenten suchen. Aber ich bin mir zu 99 % sicher, dass dies die richtige Antwort ist.
Alte Antwort:
Ein Exit-Status ungleich Null von einem Befehl in einem Bash-Skript beendet das Programm nicht. Wenn Sie einen echo $?
machen nach ./script2.sh
es wird 130 angezeigt. Sie können das Skript mit set -e
beenden wie phs vorschlägt.
$ help set
...
-e Exit immediately if a command exits with a non-zero status.
Der zweite Teil der aktualisierten Antwort von @seanmcl ist korrekt und der Link zu http://www.cons.org/cracauer/sigint.html ist wirklich gut, um ihn sorgfältig durchzulesen.
Aus diesem Link "Sie können den richtigen Exit-Status nicht durch einen Exit(3) mit einem speziellen numerischen Wert 'fälschen', selbst wenn Sie den numerischen Wert für Ihr System nachschlagen ". Genau das wird in der script2.sh von @Hermann Speiche versucht.
Eine Antwort besteht darin, den Funktionshandler in script2.sh wie folgt zu ändern:
function handler {
# ... do stuff ...
trap INT
kill -2 $$
}
Dadurch wird der Signal-Handler effektiv entfernt und das SIGINT "erneut" ausgegeben, wodurch der Bash-Prozess mit den entsprechenden Flags beendet wird, sodass sein übergeordneter Bash-Prozess dann das ursprünglich an ihn gesendete SIGINT korrekt verarbeitet. Auf diese Weise mit set -e
oder irgendein anderer Hack ist eigentlich nicht erforderlich.
Es ist auch erwähnenswert, dass, wenn Sie eine ausführbare Datei haben, die sich beim Senden eines SIGINT falsch verhält (sie entspricht nicht dem "Wie man ein richtiges Programm ist" im obigen Link, z. B. wird sie mit einem normalen Rückgabecode beendet), eine Möglichkeit Um dies zu umgehen, packen Sie den Aufruf dieses Prozesses in ein Skript wie das folgende:
#!/bin/bash
function handler {
trap INT
kill -2 $$
}
trap handler INT
badprocess "[email protected]"