Hier ist ein einfaches Skript, das ein temporäres Verzeichnis im aktuellen Verzeichnis und eine Trap-Funktion zum Löschen dieses Verzeichnisses beim Beenden einrichtet.
#filename: script
set -x
trap 'rm -rf "$d"' exit
d=`TMPDIR=$PWD mktemp -d`
"$@"
Wenn ich ksh script sleep 100
oder mache bash script sleep 100
und es mit unterbreche, C-C
wird der Trap ausgeführt und das Verzeichnis gelöscht. Mit funktioniert es nicht dash
. Warum? Ist das ein Fehler oder beabsichtigtes Verhalten?
Antwort1
zsh
, pdksh
(allerdings nicht neuere Versionen von , die mksh
davon abgeleitet sind), yash
, die Bourne-Shell verhält sich wie dash
.
Nur bash
, ksh88
, ksh93
und mksh
verhalten sich anders.
SIGINT
Aus der POSIX-Spezifikation geht nicht eindeutig hervor, welches Verhalten korrekt sein sollte, aber es gibt dort keinen Hinweis darauf, dass die Shell den Standardhandler für das (oder ein anderes) Signal überschreiben darf .
Dort heißt es, EXIT
dass die Trap-Aktion ausgewertet werden soll, wenn exit
sie aufgerufen wird. Soweit ich weiß, wird dort jedoch nicht einmal angegeben, ob sie beispielsweise ausgewertet werden soll, wenn die Shell aufgrund von set -e
Fehlerbedingungen set -u
wie Syntaxfehlern oder fehlgeschlagenen speziellen integrierten Funktionen beendet wird.
Um beim Empfang eines Signals eine Trap ausführen zu können EXIT
, müsste die Shell einen Handler für dieses Signal installieren.
Das ist ksh
, was mksh
und bash
tun, aber die Liste der Signale, die sie verarbeiten, ist bei allen drei Implementierungen unterschiedlich. Die einzigen gemeinsamen Signale bei allen drei scheinen INT
, QUIT
, TERM
, ALRM
und zu sein HUP
.
Wenn Sie möchten, dass die EXIT
Trap bei bestimmten Signalen ausgeführt wird, besteht die portable Möglichkeit darin, diese Signale selbst zu verarbeiten:
trap 'exit 1' INT HUP QUIT TERM ALRM USR1
trap 'cleanup' EXIT
Dieser Ansatz funktioniert jedoch nicht mit , da dieses Trap zsh
nicht ausführt , wenn es von einem Trap-Handler aufgerufen wird.EXIT
exit
Außerdem wird Ihr Tod Ihren Eltern nicht per Signal gemeldet.
Sie könnten stattdessen Folgendes tun:
for sig in INT QUIT HUP TERM ALRM USR1; do
trap "
cleanup
trap - $sig EXIT
kill -s $sig "'"$$"' "$sig"
done
trap cleanup EXIT
Beachten Sie jedoch, dass während der Ausführung weitere Signale eintreffen cleanup
und cleanup
möglicherweise erneut ausgeführt werden. Sie sollten sicherstellen, dass Ihr cleanup
Programm auch bei mehrmaligem Aufruf korrekt funktioniert und/oder Signale während der Ausführung ignoriert.
Antwort2
Achtung: exit
Es gibt keine Garantie, dass es funktioniert. Sie sollten stattdessen verwendenEXIT
Da der POSIX-Standard nicht definiert, ob der EXIT
Trap auch im Falle eines Signals ausgeführt werden soll, und da die Bourne Shell den EXIT
Trap in dem von Ihnen genannten Fall nicht aufruft, ist es offensichtlich, dass Sienicht spezifiziertVerhalten.