Trap-Handler für Bereinigung und Signale
Registrieren Sie EXIT-, ERR- und INT-Traps, um temporäre Dateien zu entfernen und unvollständige Änderungen zuverlässig zurückzurollen.
Trap-Handler für Bereinigung und Signale ist eine kostenlose Linux Command Line & Bash Scripting Mastery-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Linux Command Line & Bash Scripting Mastery-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Linux Command Line & Bash Scripting Mastery-Kurs umfasst insgesamt 4 Lektionen.
Warum Trap-Handler wichtig sind
Wenn ein Bash-Skript beendet wird — normal, aufgrund eines Fehlers oder weil Sie Strg+C gedrückt haben — können temporäre Dateien, unvollständig geschriebene Daten oder ein inkonsistenter Zustand zurückbleiben. Ohne Bereinigung sammeln sich diese Überbleibsel an und verursachen schwer zu debuggende Probleme.
Trap-Handler lösen dieses Problem, indem sie eine Funktion oder einen Befehl registrieren, den Bash automatisch ausführt, wenn ein bestimmtes Signal oder Pseudo-Signal empfangen wird.
- EXIT — wird immer ausgelöst, wenn das Skript beendet wird, unabhängig vom Grund
- ERR — wird ausgelöst, nachdem ein Befehl einen Exit-Status ungleich null zurückgibt
- INT — wird ausgelöst, wenn der Benutzer SIGINT (Strg+C) sendet
- TERM — wird bei SIGTERM ausgelöst (z. B. durch
kill)
Ein gut geschriebenes Skript registriert diese Traps ganz am Anfang, bevor riskante Arbeiten beginnen.
Die Syntax des trap-Builtins
Das trap-Builtin registriert einen Handler für ein oder mehrere Signale oder Pseudo-Signale. Die allgemeine Syntax lautet:
trap 'command_or_function' SIGNAL [SIGNAL...]
Wichtige Regeln:
- Das erste Argument ist eine in Anführungszeichen gesetzte Zeichenfolge mit Shell-Code (oder ein Funktionsname), der beim Auslösen des Signals ausgeführt wird.
- Nach dem Handler können Sie mehrere Signale angeben.
trap '' SIGNALignoriert das Signal (leerer Handler).trap - SIGNALsetzt das Signal auf sein Standardverhalten zurück.
Traps werden von Funktionen übernommen, die in derselben Shell aufgerufen werden, jedoch nicht von Subshells, die mit ( ) oder & gestartet werden.
#!/usr/bin/env bash
# Syntax examples — not a full script
# Register a cleanup function on EXIT
trap cleanup EXIT
# Inline handler for INT and TERM
trap 'echo "Interrupted!"; exit 1' INT TERM
# Ignore SIGHUP
trap '' HUP
# Reset SIGPIPE to default
trap - PIPEDer EXIT-Trap — Ihr Sicherheitsnetz
Das EXIT-Pseudo-Signal ist der wichtigste Trap, den Sie registrieren sollten. Es wird ausgelöst, wenn die Shell aus jedem Grund beendet wird: nach normaler Ausführung, durch exit N, wegen eines unbehandelten Fehlers oder aufgrund eines Signals. Dadurch eignet es sich ideal zum Entfernen temporärer Dateien.
Bewährte Vorgehensweise:
- Erstellen Sie temporäre Dateien mit
mktemp, damit der Name eindeutig und nicht vorhersehbar ist. - Speichern Sie den Pfad sofort in einer Variablen.
- Registrieren Sie den EXIT-Trap direkt nach der Erstellung, damit die Bereinigung immer ausgeführt wird.
Der Exit-Code des Skripts bleibt erhalten — der Exit-Code des Trap-Handlers wird ignoriert, sofern Sie darin nicht ausdrücklich exit aufrufen.
#!/usr/bin/env bash
set -euo pipefail
TMPFILE=$(mktemp /tmp/myapp.XXXXXX)
cleanup() {
echo "Removing temp file: $TMPFILE" >&2
rm -f "$TMPFILE"
}
trap cleanup EXIT
# Do real work
echo "Processing..." > "$TMPFILE"
sort "$TMPFILE" -o "$TMPFILE"
cp "$TMPFILE" /tmp/myapp_result.txt
echo "Done. Result saved."Mehrere temporäre Dateien und Verzeichnisse verwalten
In realen Skripten werden häufig mehrere temporäre Objekte erstellt — Dateien, Verzeichnisse, FIFOs und Lock-Dateien. Statt jedes Objekt einzeln zu verwalten, sammeln Sie sie in einem Array und entfernen alles in einer einzigen Bereinigungsfunktion.
Dieses Muster lässt sich problemlos erweitern: Hängen Sie jedes neue temporäre Objekt beim Erstellen an das Array an. Der EXIT-Trap verarbeitet unabhängig davon, an welcher Stelle das Skript beendet wird, immer die vollständige Liste.
#!/usr/bin/env bash
set -euo pipefail
CLEANUP_TARGETS=()
add_cleanup() {
CLEANUP_TARGETS+=("$1")
}
cleanup() {
echo "Running cleanup..." >&2
for target in "${CLEANUP_TARGETS[@]:-}"; do
rm -rf "$target"
echo "Removed: $target" >&2
done
}
trap cleanup EXIT
# Create and track temp resources
TMPDIR_WORK=$(mktemp -d /tmp/work.XXXXXX)
add_cleanup "$TMPDIR_WORK"
TMPFILE_LOG=$(mktemp /tmp/run.XXXXXX.log)
add_cleanup "$TMPFILE_LOG"
echo "Working in $TMPDIR_WORK" | tee "$TMPFILE_LOG"
touch "$TMPDIR_WORK/output.txt"
echo "Step complete."Der ERR-Trap — Fehler abfangen
Das ERR-Pseudo-Signal wird ausgelöst, nachdem ein einfacher Befehl einen Exit-Status ungleich null zurückgibt, sofern die Shell-Option set -e (errexit) aktiv ist oder sich der Befehl nicht innerhalb eines if, while oder einer mit ||/&& gebildeten zusammengesetzten Anweisung befindet.
Verwenden Sie den ERR-Trap, um:
- mithilfe von
$LINENOund$BASH_COMMANDzu protokollieren, in welcher Zeile der Fehler aufgetreten ist. - vor dem Ausführen des EXIT-Traps eine Rollback-Logik auszulösen.
- strukturierte Fehlermeldungen nach stderr auszugeben.
Wichtig: ERR-Traps werden innerhalb von Funktionen nicht ausgelöst, sofern Sie nicht ausdrücklich set -E (errtrace) ausführen, damit Funktionen den ERR-Trap der aufrufenden Shell übernehmen.
#!/usr/bin/env bash
set -eEuo pipefail
on_error() {
local exit_code=$?
local line=$1
echo "ERROR: command failed with exit code $exit_code at line $line" >&2
echo " Command: $BASH_COMMAND" >&2
}
trap 'on_error $LINENO' ERR
echo "Starting task..."
cp /nonexistent/file /tmp/ # This will fail
echo "This line is never reached."Der INT-Trap — Strg+C ordnungsgemäß behandeln
Durch das Drücken von Strg+C wird SIGINT an die Prozessgruppe im Vordergrund gesendet. Ohne Trap beendet sich Bash sofort, wobei möglicherweise unvollständige Arbeiten zurückbleiben.
Durch das Registrieren eines INT-Traps können Sie:
- eine verständliche Abbruchmeldung für Benutzer ausgeben.
- vor der Übergabe an den EXIT-Trap ein eventuell erforderliches Zwischen-Rollback durchführen.
- mit einem aussagekräftigen Statuscode beenden (
130ist der übliche Code für SIGINT:128 + 2).
Rufen Sie nach Abschluss Ihres INT-Handlers exit 130 auf, um den korrekten Exit-Code weiterzugeben. Der EXIT-Trap wird anschließend automatisch ausgeführt.
#!/usr/bin/env bash
set -euo pipefail
TMPFILE=$(mktemp /tmp/demo.XXXXXX)
cleanup() {
rm -f "$TMPFILE"
echo "Temp file removed." >&2
}
on_interrupt() {
echo "" >&2
echo "Caught SIGINT — cancelling gracefully." >&2
exit 130 # EXIT trap (cleanup) runs automatically after this
}
trap cleanup EXIT
trap on_interrupt INT
echo "Running long task. Press Ctrl+C to cancel."
for i in $(seq 1 10); do
echo "Step $i/10..."
sleep 1
done
echo "All steps complete."EXIT-, ERR- und INT-Traps kombinieren
In Produktionsskripten registrieren Sie normalerweise alle drei Traps gemeinsam, um jeden Beendigungspfad abzudecken:
- EXIT — wird immer ausgeführt und übernimmt die Dateibereinigung.
- ERR — protokolliert den fehlerhaften Befehl und die Zeilennummer.
- INT — gibt eine Abbruchmeldung aus und beendet sich mit dem Code 130.
Da EXIT immer zuletzt ausgeführt wird, muss Ihre Bereinigungslogik nur an einer Stelle stehen. ERR- und INT-Handler können sich auf das Protokollieren und das Setzen des Zustands konzentrieren und die eigentliche Bereinigung an EXIT delegieren, indem sie exit aufrufen.
Verwenden Sie am Anfang set -eEuo pipefail, damit auch Fehler in Funktionen ERR auslösen und pipefail Fehler innerhalb von Pipelines erkennt.
#!/usr/bin/env bash
set -eEuo pipefail
TMPFILE=$(mktemp /tmp/combined.XXXXXX)
ROLLBACK_NEEDED=false
cleanup() {
if [[ "$ROLLBACK_NEEDED" == true ]]; then
echo "Rolling back partial changes..." >&2
fi
rm -f "$TMPFILE"
echo "Cleanup done." >&2
}
on_error() {
ROLLBACK_NEEDED=true
echo "ERR at line $1: $BASH_COMMAND" >&2
}
on_interrupt() {
echo "Interrupted by user." >&2
exit 130
}
trap cleanup EXIT
trap 'on_error $LINENO' ERR
trap on_interrupt INT
echo "hello" > "$TMPFILE"
echo "Script finished successfully."Traps dynamisch zurücksetzen und deaktivieren
Manchmal müssen Sie einen Trap mitten im Skript ändern — beispielsweise eine einmalige Bereinigung nach Abschluss eines kritischen Abschnitts, damit nachfolgende normale Vorgänge kein unnötiges Rollback auslösen.
trap - SIGNALsetzt das Signal auf sein integriertes Standardverhalten zurück.trap '' SIGNALignoriert das Signal vollständig (der Prozess kann dadurch nicht beendet werden).- Sie können jederzeit einen neuen Handler registrieren; der letzte Aufruf von
trapgilt.
Ein häufiges Muster besteht darin, den EXIT-Trap zu aktualisieren, sobald ein riskanter Vorgang erfolgreich war, und dabei von einem Rollback-Handler zu einem einfachen Bereinigungs-Handler zu wechseln.
#!/usr/bin/env bash
set -euo pipefail
TMPFILE=$(mktemp /tmp/staged.XXXXXX)
rollback() {
echo "ROLLBACK: removing $TMPFILE" >&2
rm -f "$TMPFILE"
}
cleanup_only() {
echo "CLEANUP: removing $TMPFILE" >&2
rm -f "$TMPFILE"
}
# Start with rollback in case something fails during the risky phase
trap rollback EXIT
echo "Performing risky operation..."
echo "critical data" > "$TMPFILE"
# ... imagine more risky steps here ...
# Risky phase succeeded — switch to simple cleanup
trap cleanup_only EXIT
echo "Risky phase done. Now doing safe finalization."
cp "$TMPFILE" /tmp/staged_result.txt
echo "All done."Exit-Codes durch Traps weitergeben
Eine subtile Falle: Enthält Ihre Bereinigungsfunktion Befehle, die fehlschlagen können, wird möglicherweise der endgültige Exit-Code des Skripts überschrieben. Bewahren Sie den ursprünglichen Exit-Code ausdrücklich auf.
Innerhalb eines Trap-Handlers enthält $? den Exit-Code, der den Trap ausgelöst hat. Speichern Sie ihn in der allerersten Zeile des Handlers, bevor ein anderer Befehl seinen Wert ändert.
#!/usr/bin/env bash
set -euo pipefail
TMPFILE=$(mktemp /tmp/exitcode.XXXXXX)
cleanup() {
local original_exit=$? # capture BEFORE any other command
echo "Cleaning up (original exit: $original_exit)" >&2
rm -f "$TMPFILE"
# Exit with the original code so callers see the real result
exit "$original_exit"
}
trap cleanup EXIT
echo "Doing work..."
echo "data" > "$TMPFILE"
# Simulate failure
if [[ ! -f /tmp/required_marker ]]; then
echo "Required marker missing!" >&2
exit 2
fi
echo "Done."Traps in Funktionen und Subshells
Das Verständnis der Vererbung von Traps ist entscheidend, um korrekte Skripte zu schreiben:
- Funktionen werden in derselben Shell ausgeführt und übernehmen Traps — ERR wird jedoch nur dann an Funktionen weitergegeben, wenn
set -E(errtrace) aktiv ist. - Subshells (
( ... )) beginnen mit einer Kopie der Traps des übergeordneten Prozesses, aber Änderungen innerhalb der Subshell wirken sich nicht auf den übergeordneten Prozess aus. - Hintergrundjobs (
cmd &) sind Subshells und übernehmen die INT-/TERM-Traps des übergeordneten Prozesses nicht (für sie gilt die standardmäßige Signalbehandlung).
Praktische Regel: Registrieren Sie Ihre Traps im Hauptteil des Skripts, verwenden Sie set -E, wenn ERR an Funktionen weitergegeben werden soll, und verlassen Sie sich niemals auf die Vererbung von Traps über & hinweg.
#!/usr/bin/env bash
set -eEuo pipefail # -E = errtrace: ERR propagates into functions
on_error() {
echo "ERR in function or main at line $1" >&2
}
trap 'on_error $LINENO' ERR
risky_function() {
echo "Inside risky_function"
ls /nonexistent_path # triggers ERR — works because of set -E
}
# Subshell: has its own copy; changes don't affect parent
(
trap '' ERR # disable ERR only inside subshell
ls /nonexistent_path 2>/dev/null || true
echo "Subshell completed without triggering parent ERR"
)
risky_functionPraxisbeispiel: Atomisches Ersetzen von Dateien
Ein klassisches robustes Bash-Muster ist das atomische Ersetzen von Dateien: Schreiben Sie in eine temporäre Datei und benennen Sie diese anschließend an die Zielposition um. Wenn vor dem Umbenennen etwas fehlschlägt, bleibt das Original unverändert. Traps machen dieses Verfahren besonders zuverlässig.
Schritte:
- Erstellen Sie eine temporäre Datei im gleichen Dateisystem wie das Ziel (damit
mvatomar ist). - Registrieren Sie einen EXIT-Trap, der die temporäre Datei entfernt, falls das Skript vorzeitig beendet wird.
- Schreiben und validieren Sie den neuen Inhalt.
- Benennen Sie die Datei atomar um (
mv) — erst jetzt wird das Original ersetzt. - Der EXIT-Trap entfernt die temporäre Datei nur, wenn sie noch vorhanden ist (nach einem erfolgreichen
mvist sie verschwunden).
#!/usr/bin/env bash
set -euo pipefail
DEST="/tmp/important_config.conf"
TMPFILE=$(mktemp "$(dirname "$DEST")/.tmp.XXXXXX")
cleanup() {
rm -f "$TMPFILE" # no-op if mv already moved it
}
trap cleanup EXIT
# Write new content to temp file
cat > "$TMPFILE" <<'EOF'
[settings]
version=2
mode=production
EOF
# Validate before replacing
if ! grep -q 'version=' "$TMPFILE"; then
echo "Validation failed — aborting replacement" >&2
exit 1
fi
# Atomic rename — DEST is replaced only here
mv "$TMPFILE" "$DEST"
echo "Config updated atomically: $DEST"Wissenscheck: Vererbung des ERR-Traps
Testen Sie Ihr Verständnis dafür, wie sich der ERR-Trap bei Funktionen in Bash verhält.
Zusammenfassung: Trap-Handler für Bereinigung und Signale
In dieser Lektion haben Sie gelernt, wie Sie Bash-Skripte mithilfe von Trap-Handlern robust machen:
- EXIT ist Ihr universelles Sicherheitsnetz — registrieren Sie ihn sofort nach dem Erstellen eines temporären Objekts und speichern Sie immer zuerst
$?, um den ursprünglichen Exit-Code zu bewahren. - ERR ermöglicht das Protokollieren von Fehlern mit
$LINENOund$BASH_COMMAND; verwenden Sieset -E, damit Funktionen den Trap übernehmen. - INT behandelt Strg+C ordnungsgemäß — geben Sie eine Meldung aus und beenden Sie sich mit dem Code 130, damit EXIT die Bereinigung übernimmt.
- Sammeln Sie temporäre Objekte in einem Array und entfernen Sie sie alle in einer einzigen Bereinigungsfunktion.
- Verwenden Sie
trap - SIGNALzum Zurücksetzen undtrap '' SIGNALzum dynamischen Ignorieren von Signalen. - Das atomare Umbenennungsmuster (
mktemp→ Schreiben → Validieren →mv) stellt zusammen mit einem EXIT-Trap sicher, dass unvollständige Schreibvorgänge niemals die Zieldatei beschädigen.
Die Kombination aus set -eEuo pipefail und gut platzierten Traps bietet eine solide Grundlage für robuste Bash-Produktionsskripte.
Häufig gestellte Fragen
Ist die Lektion „Trap-Handler für Bereinigung und Signale“ kostenlos?
Ja — der vollständige Text von „Trap-Handler für Bereinigung und Signale“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Linux Command Line & Bash Scripting Mastery-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Linux Command Line & Bash Scripting Mastery-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Trap-Handler für Bereinigung und Signale“?
Registrieren Sie EXIT-, ERR- und INT-Traps, um temporäre Dateien zu entfernen und unvollständige Änderungen zuverlässig zurückzurollen. Du übst Linux Command Line & Bash Scripting Mastery mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Linux Command Line & Bash Scripting Mastery zu starten?
Keine Vorkenntnisse erforderlich. Linux Command Line & Bash Scripting Mastery auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.
Wie lange dauert die Lektion „Trap-Handler für Bereinigung und Signale“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Linux Command Line & Bash Scripting Mastery-Lektion Code schreiben und ausführen?
Ja. Jede Linux Command Line & Bash Scripting Mastery-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Strict Mode mit set -euo pipefail
- Trap-Handler für Bereinigung und Signale
- Sichere temporäre Dateien und Sperrverzeichnisse
- Idempotente Skripte und Wiederholungslogik mit Backoff