Kontext:
Ich habe ein Bash-Skript, das eine Subshell und einen Trap für das Pseudo-Signal EXIT enthält und Interrupts während eines rsync
nicht korrekt abfängt. Hier ist ein Beispiel:
Die Idee des Skripts ist folgende: Die meiste wichtige Logik läuft in einer Subshell, die durch tee
und eine Logdatei geleitet wird, also muss ich nicht jede einzelne Zeile der Hauptlogik tee
Lass es alles geloggt werden. Immer wenn die Subshell endet oder das Skript aus irgendeinem Grund angehalten wird (das EXIT-Pseudosignal sollte alle diese Fälle erfassen), fängt der Trap es ab und führt die cleanup()
-Funktion aus und entfernt dann den Trap. Die Befehle rsync
und sleep
(der Ruhezustand ist nur ein Beispiel) werden durch exec
ausgeführt, um die Erstellung von Zombie-Prozessen zu verhindern, wenn ich das übergeordnete Skript während der Ausführung und jeden potenziell lang laufenden Befehl abbringe ist in eine eigene Subshell eingebunden, so dass bei Beendigung von exec
das ganze Skript nicht beendet wird.
Das Problem:
Wenn ich das Skript (über kill
oder STRG + C) während des Befehls exec / subshell wrapped sleep
abbringe, funktioniert das Trap korrekt und ich sehe "Cleaning up!" echoed und protokolliert. Wenn ich das Skript während des Befehls rsync
abbringe, sehe ich rsync
end und schreibe rsync error: received SIGINT, SIGTERM, or SIGHUP (code 20) at rsync.c(544) [sender=3.0.6]
auf den Bildschirm, und dann stirbt das Skript ab; keine Aufräumarbeiten, keine Überfüllung. Warum löst eine Unterbrechung / Abtötung von rsync
die Falle nicht aus?
Ich habe versucht, den Schalter --no-detach
mit rsync zu verwenden, aber es hat nichts geändert.
Ich habe Bash 4.1.2, rsync 3.0.6, CentOS 6.2.
Der Interrupt wird korrekt abgefangen, wenn Sie INT dem Trap hinzufügen
%Vor% Bash fängt die Überfüllung korrekt ab. Dies stellt jedoch nicht die Frage, warum das Skript beim Beenden abfängt, wenn sleep
unterbrochen ist, oder warum es nicht auf rsync
triggert, sondern das Skript so ausführt, wie es soll. Hoffe, das hilft.
Zusätzlich zu set -e
denke ich, dass du set -E
:
Falls gesetzt, wird jeder Trap auf ERR von Shell-Funktionen, Befehlsersetzungen und Befehlen in einer Subshell-Umgebung geerbt. Die ERR-Falle wird normalerweise in solchen Fällen nicht vererbt.
Alternativ können Sie, statt Ihre Befehle in Subshells zu verpacken, geschweifte Klammern verwenden, die Ihnen weiterhin die Möglichkeit geben, Befehlsausgaben umzuleiten, aber sie in der aktuellen Shell ausführen.
Ihre Shell ist möglicherweise so konfiguriert, dass sie bei einem Fehler beendet wird:
%Vor% Wenn Sie sleep
(^ C) unterbrechen, wird die Untershell aufgrund von set -e
und print woah
im Prozess beendet.
Auch etwas unzusammenhängend: Ihr trap - EXIT
befindet sich (explizit) in einer Subshell, also hat es keine Wirkung, nachdem die Aufräumfunktion