trap und mktemp – Skripte, die auch nach einem Abbruch aufräumen
Ein Skript legt eine temporäre Datei an, bricht in der Mitte ab – und die Datei bleibt liegen. Nach ein paar Wochen ist /tmp voll und niemand weiß, woher der Müll kommt. Zwei Zeilen lösen das dauerhaft.
Fast jedes Skript, das etwas herunterlädt, umwandelt oder vergleicht, braucht eine Zwischendatei. Und fast jedes räumt sie am Ende auf – am glücklichen Ende. Bricht es vorher ab, weil der Download scheiterte oder jemand Strg+C drückt, bleibt sie liegen.
Der feste Rahmen
#!/usr/bin/env bash
set -euo pipefail
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT
curl -fsSL "$url" -o "$tmp/daten.json"
jq '.items[]' "$tmp/daten.json" > "$tmp/gefiltert.txt"
mv "$tmp/gefiltert.txt" ./ergebnis.txttrap … EXIT wird immer ausgeführt, wenn die Shell das Skript verlässt: bei Erfolg, bei einem Fehler (dank set -e), bei Strg+C und bei kill. Ein Aufräumer, vier Fälle.
Warum mktemp und nicht /tmp/meins.txt
tmp="$(mktemp -d)" # /tmp/tmp.8Xk2pQ, nur für dich lesbar
datei="$(mktemp)" # eine einzelne Datei
datei="$(mktemp /tmp/export-XXXXXX.csv)" # mit sprechendem NamenEin fester Pfad hat zwei Probleme: Zwei gleichzeitige Läufe überschreiben sich gegenseitig, und ein vorhandener Symlink auf einen fremden Pfad macht aus deiner Zwischendatei eine Waffe. mktemp erzeugt den Namen zufällig und die Datei mit engen Rechten.
Mehrere Dinge aufräumen
aufraeumen() {
rm -rf "${tmp:-}"
[[ -n "${pidfile:-}" ]] && rm -f "$pidfile"
docker rm -f testdb >/dev/null 2>&1 || true
}
trap aufraeumen EXITEine Funktion statt einer langen Zeile – und || true sorgt dafür, dass ein fehlschlagender Aufräumschritt nicht den Rückgabewert des Skripts verdirbt.
Signale unterscheiden
trap 'echo "Abgebrochen."; exit 130' INT TERM
trap 'echo "Fehler in Zeile $LINENO"; ' ERR
trap 'rm -rf "$tmp"' EXITEXIT– immer, zum Aufräumen.INT/TERM– Strg+C bzw.kill, für eine eigene Meldung.ERR– bei jedem fehlgeschlagenen Befehl (zusammen mitset -esehr nützlich für Protokolle).
Wichtig: Für dieselbe Falle gilt immer nur der letzte trap. Mehrere Aufräumer gehören in eine Funktion, nicht in mehrere Aufrufe.
Fallstrick
Zwei Stolpersteine. Erstens Anführungszeichen: trap "rm -rf $tmp" EXIT wertet $tmp sofort aus – ist die Variable da noch leer, steht in der Falle rm -rf. Mit einfachen Anführungszeichen wird sie erst beim Auslösen ausgewertet. Zweitens: set -e beendet keine Subshell-Pipelines wie erwartet, und in einer Funktion, deren Rückgabewert geprüft wird, greift es gar nicht – verlass dich also nicht allein darauf, sondern prüfe kritische Befehle ausdrücklich.
Skripte, die man nachts laufen lassen kann, ohne morgens aufzuräumen, schreibe ich gern. Melde dich über bymw.de.
Quellen
Du brauchst mehr als ein Snippet?
Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.
Projekt anfragen →Verwandte Snippets
Heredocs in Bash – mehrzeilige Texte, Konfigurationen und SQL ohne Echo-Wüste
Zwanzig echo-Zeilen für eine Konfigurationsdatei sind mühsam und fehleranfällig. Ein Heredoc schreibt den Text so, wie er aussehen soll – mit oder ohne Variablen, je nachdem, wie du den Marker schreibst.
Standardwerte und Pflichtvariablen in Bash – ${VAR:-…} und ${VAR:?…}
Fehlt eine Umgebungsvariable, läuft das Skript oft trotzdem los – und löscht dann /backup/ statt /backup/kunde42/. Die Shell kann Standardwerte setzen und fehlende Werte laut einfordern, ohne eine einzige if-Abfrage.
Warum "$@" in Anführungszeichen gehört – Quoting und Arrays in Bash
Ein Dateiname mit Leerzeichen, und aus einem Argument werden zwei. Das ist keine Kleinigkeit: Genau daraus entstehen Skripte, die die falsche Datei löschen. Die Regeln dafür passen auf eine Seite.