Führen Sie einen Befehl oder eine Funktion aus, wenn SIGINT oder SIGTERM an das übergeordnete Skript selbst gesendet wird, nicht an die untergeordneten Prozesse

11

Nehmen wir an, ich habe das script.sh

#!/bin/bash
exit_script() {
    echo "Printing something special!"
    echo "Maybe executing other commands!"
    kill -- -$$ # Sends SIGTERM to child/sub processes
}

echo "Some other text"
#other commands here
sleep infinity

Ich möchte script.shdie Funktion ausführen, exit_scriptwann immer sie empfängt SIGINToder SIGTERM Zum Beispiel:

killall script.sh # it will send SIGTERM to my script

und ich möchte, dass mein Skript dies ausführt

exit_script() {
    echo "Printing something special!"
    echo "Maybe executing other commands!"
    kill -- -$$ # Sends SIGTERM to child/sub processes
}

Ich habe versucht, diese Funktion mit zu implementieren trap

trap exit_script SIGINT SIGTERM

Die Person, die meine Frage beantwortet hat, hat mir das Gegenteil bewiesen.
aber es hat nicht funktioniert, weil trapes nur auf Signale zu reagieren scheint, die an untergeordnete / untergeordnete Prozesse gesendet werden. Als Anfänger konnte ich die trapManpage nicht entziffern , daher habe ich wahrscheinlich die Lösung verpasst.

Ich denke, das ist es, was "echte" Programme wie Chromium tun, wenn Sie sie senden SIGTERM

Von https://major.io/2010/03/18/sigterm-vs-sigkill/

Die Anwendung kann bestimmen, was sie tun möchte, sobald ein SIGTERM empfangen wurde. Während die meisten Anwendungen ihre Ressourcen bereinigen und stoppen, können einige nicht.

bosa djo
quelle
2
Im Allgemeinen werden Schwüre für einen respektvollen Diskurs als unangemessen angesehen
Katze
Bearbeitungsvorschlag genehmigt ok, ok gemacht, kein Spaß ich bekomme es
bosa djo
Es ist nicht so, dass kein Spaß erlaubt ist, es wird nur als anstößig angesehen
Katze
1
@cat Ich habe über Ihre Argumentation nachgedacht und Sie haben Recht, entschuldigen Sie meine Dummheit
bosa djo

Antworten:

15

trapreagiert auf die aufrufenden Prozesssignale selbst. Sie müssen es jedoch anrufen, bevor das Signal empfangen wird. Ich meine, am Anfang Ihres Drehbuchs.

Wenn Sie außerdem verwenden möchten kill -- -$$, das das Signal auch an Ihr Skript sendet, müssen Sie die Falle löschen, bevor Sie den Kill ausführen . Andernfalls endet die Endlosschleife.

Zum Beispiel:

#!/bin/bash
exit_script() {
    echo "Printing something special!"
    echo "Maybe executing other commands!"
    trap - SIGINT SIGTERM # clear the trap
    kill -- -$$ # Sends SIGTERM to child/sub processes
}

trap exit_script SIGINT SIGTERM

echo "Some other text"
#other commands here
sleep infinity

Wie in den Kommentaren erläutert, besteht das Problem darin, dass das Skript das Signal empfängt, aber auf das Ende des Ruheprogramms wartet, bevor das empfangene Signal verarbeitet wird. Sie sollten also die untergeordneten Prozesse (in diesem Fall den Schlafprozess) beenden, um die Trap-Aktion auszuführen. Sie können dies mit etwas wie dem folgenden tun:

kill -- -$(pgrep script.sh)

Oder wie in den Kommentaren angegeben:

killall -g script.sh
zuazo
quelle
1
Ich vermisse wahrscheinlich etwas, weil es nicht funktioniert. Hier ist, was ich tue. script.sh &; killall script.sh aber es macht nichts.
Bosa Djo
Ich führe das script.sh &; # dann mache ich mein Geschäft; killall script.sh und es tötet script.sh nicht
bosa djo
1
Das Problem ist wahrscheinlich, dass das Skript das Signal empfängt, aber auf das Ende des Schlafprogramms wartet, bevor es verarbeitet wird. Versuchen Sie mit ./script.sh & sleep 1 && kill -- -$(pgrep script.sh), ein Kill-Signal auch an die untergeordneten Prozesse Ihres Skripts zu senden.
Zuazo
@zuazo Sie sollten diese interessanten und wichtigen Informationen zu Ihrer Antwort hinzufügen :)
Katze
1
Schön, bosa djo. Ich habe Ihre alternative Lösung zur Antwort hinzugefügt
;-)