Sichere temporäre Dateien und Sperrverzeichnisse
Verwenden Sie mktemp und flock, um vor Race Conditions geschützte temporäre Ressourcen zu erstellen und parallele Skriptausführungen zu verhindern.
Sichere temporäre Dateien und Sperrverzeichnisse ist eine kostenlose DevOps Bootcamp-Lektion auf CoddyKit. Dies ist Lektion 3 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 DevOps Bootcamp-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der DevOps Bootcamp-Kurs umfasst insgesamt 4 Lektionen.
Warum temporäre Dateien ein Sicherheitsrisiko darstellen
Bash-Skripte benötigen häufig temporären Speicher — für Zwischenergebnisse, Sperrmarkierungen und Staging-Bereiche. Werden temporäre Dateien jedoch unachtsam erstellt, entstehen schwerwiegende Sicherheitslücken.
- Race Conditions: Ein anderer Prozess kann den Dateinamen vorhersagen und die Datei zuerst erstellen, sodass Ihre Schreibvorgänge umgeleitet werden.
- Symlink-Angriffe: Ein Angreifer erstellt am erwarteten Pfad einen Symlink, der auf eine sensible Datei wie
/etc/passwdverweist. - Zurückgelassene Dateien: Wenn ein Skript abstürzt, sammeln sich temporäre Dateien an und können vertrauliche Daten offenlegen.
Die beiden zentralen Werkzeuge, die diese Probleme verhindern, sind mktemp und flock. In dieser Lektion lernen Sie, wie Sie beide sicher und robust einsetzen.
Sichere temporäre Dateien mit mktemp erstellen
mktemp erstellt eine temporäre Datei mit einem zufälligen, nicht vorhersehbaren Namen und gibt deren Pfad zurück. Die Datei wird atomar erstellt, sodass kein anderer Prozess den Namen zuerst verwenden kann.
- Syntax:
mktemp [TEMPLATE]— die Vorlage muss mit mindestens dreiX-Zeichen enden. - Jedes
Xwird durch ein zufälliges Zeichen ersetzt, wodurch ein eindeutiger Name wie/tmp/script.aB3kQzentsteht. - Die Datei wird automatisch mit den Berechtigungen
0600erstellt (nur der Eigentümer kann sie lesen).
Speichern Sie den zurückgegebenen Pfad immer sofort in einer Variablen, damit Sie später darauf zugreifen und die Datei bereinigen können.
#!/usr/bin/env bash
set -euo pipefail
# Create a secure temp file
TMPFILE=$(mktemp /tmp/myapp.XXXXXX)
echo "Temp file created at: $TMPFILE"
# Write data to it
echo "some intermediate result" > "$TMPFILE"
# Read it back
cat "$TMPFILE"
# Clean up
rm -f "$TMPFILE"Immer mit einem trap bereinigen
Wenn Ihr Skript unerwartet beendet wird — aufgrund eines Fehlers, eines Signals oder weil set -e ausgelöst wurde — bleiben temporäre Dateien zurück, sofern Sie keinen Bereinigungs-Handler registrieren.
Das trap-Builtin führt einen Befehl aus, wenn die Shell ein Signal empfängt oder beendet wird. Das übliche Muster zur Bereinigung temporärer Dateien lautet:
- Registrieren Sie den Trap direkt nach dem Erstellen der temporären Datei.
- Verwenden Sie
EXITals Trap, damit die Bereinigung sowohl bei normaler als auch bei abnormaler Beendigung ausgeführt wird. - Verwenden Sie außerdem
INTundTERMals Traps, wenn das Skript lange läuft oder interaktiv ist.
So bleiben auch dann keine verwaisten Dateien zurück, wenn das Skript während der Ausführung beendet wird.
#!/usr/bin/env bash
set -euo pipefail
TMPFILE=$(mktemp /tmp/report.XXXXXX)
# Register cleanup before doing any real work
cleanup() {
rm -f "$TMPFILE"
echo "Cleaned up $TMPFILE" >&2
}
trap cleanup EXIT
# Do work — even if this fails, cleanup() will run
echo "Processing..." > "$TMPFILE"
grep "result" "$TMPFILE" || true
echo "Done. File will be removed on exit."Temporäre Verzeichnisse mit mktemp -d erstellen
Manchmal benötigen Sie ein vollständiges Verzeichnis, um mehrere Dateien zwischenzuspeichern — beispielsweise beim Erstellen eines Archivs oder beim Entpacken eines Tarballs vor der Verarbeitung. Verwenden Sie mktemp -d, um ein sicheres temporäres Verzeichnis zu erstellen.
- Das Verzeichnis wird mit den Berechtigungen
0700erstellt (Zugriff nur für den Eigentümer). - Räumen Sie es in Ihrem Trap mit
rm -rfauf — achten Sie darauf, ausschließlich die Variable und niemals einen fest codierten Pfad zu entfernen. - Verwenden Sie doppelte Anführungszeichen und prüfen Sie als zusätzliche Sicherheitsmaßnahme, dass die Variable nicht leer ist, bevor Sie
rm -rfaufrufen.
#!/usr/bin/env bash
set -euo pipefail
TMPDIR=$(mktemp -d /tmp/extract.XXXXXX)
cleanup() {
# Guard: only rm if variable is set and non-empty
[[ -n "${TMPDIR:-}" ]] && rm -rf "$TMPDIR"
}
trap cleanup EXIT
echo "Working in $TMPDIR"
# Simulate staging files
echo "file one" > "$TMPDIR/part1.txt"
echo "file two" > "$TMPDIR/part2.txt"
ls "$TMPDIR"
echo "All done."Das Problem gleichzeitig ausgeführter Skripte
Cron-Jobs, systemd-Timer und manuell gestartete Skripte können problemlos mehrere Instanzen desselben Skripts gleichzeitig starten. Dies führt zu:
- Doppelter Verarbeitung: Dieselben Datenbankeinträge oder Dateien werden zweimal verarbeitet.
- Beschädigter Ausgabe: Zwei Instanzen schreiben gleichzeitig in dieselbe Ausgabedatei.
- Deadlocks oder unvollständigem Zustand: Beide Instanzen ändern gemeinsam genutzte Ressourcen in einer verschachtelten, nicht vorhersehbaren Reihenfolge.
Die traditionelle Lösung bestand darin, eine PID-Datei zu schreiben und sie beim Start zu prüfen — dieser Ansatz hat jedoch ein Race Window zwischen Prüfung und Schreibvorgang. Die korrekte moderne Lösung ist flock. Es verwendet den Advisory-Locking-Mechanismus des Kernels und ermöglicht eine garantiert race-freie Sperre.
Sperren mit flock: Das Einzeilen-Muster
flock erwirbt eine Advisory-Sperre für einen Dateideskriptor, bevor ein Befehl ausgeführt wird. Die einfachste Verwendung besteht darin, Ihr gesamtes Skript über die Befehlszeile zu umschließen:
flock -n /var/lock/myscript.lock bash myscript.sh
-n(nicht blockierend): wird sofort mit Status 1 beendet, wenn die Sperre bereits gehalten wird, statt zu warten.- Ohne
-nblockiertflock, bis die Sperre verfügbar wird — nützlich zum Einreihen von Ausführungen. - Die Sperrdatei selbst ist nur eine Markierung; ihr Inhalt spielt keine Rolle. Sie kann problemlos zwischen den Ausführungen bestehen bleiben.
- Wenn der Prozess, der die Sperre hält, beendet wird, gibt der Kernel sie automatisch frei — eine manuelle Bereinigung ist nicht erforderlich.
#!/usr/bin/env bash
# launcher.sh — prevents concurrent runs of worker.sh
set -euo pipefail
LOCKFILE="/tmp/myworker.lock"
if ! flock -n "$LOCKFILE" bash -c 'echo "Running worker..."; sleep 2; echo "Done."'; then
echo "Another instance is already running. Exiting." >&2
exit 1
fiflock innerhalb eines Skripts mit einem Dateideskriptor
Wenn Sie innerhalb eines Skripts statt durch externes Umschließen sperren möchten, verwenden Sie exec, um einen Dateideskriptor zu öffnen, und rufen Sie anschließend flock für diesen Deskriptor auf. Dies ist das idiomatische Muster in produktiv eingesetzten Skripten.
exec 200>"$LOCKFILE"öffnet die Datei zum Schreiben auf Deskriptor 200 (und erstellt sie bei Bedarf).flock -n 200versucht, Deskriptor 200 nicht blockierend zu sperren.- Da die Sperre an den Dateideskriptor (nicht an den Dateinamen) gebunden ist, wird sie automatisch freigegeben, wenn der Shell-Prozess beendet wird.
- Deskriptornummern von 200 bis 299 werden üblicherweise verwendet, um Konflikte mit stdin/stdout/stderr zu vermeiden.
#!/usr/bin/env bash
set -euo pipefail
LOCKFILE="/tmp/myjob.lock"
# Open lock file on FD 200
exec 200>"$LOCKFILE"
# Attempt non-blocking lock
if ! flock -n 200; then
echo "ERROR: Another instance of this script is running." >&2
exit 1
fi
echo "Lock acquired. Starting work..."
sleep 1
echo "Work complete. Lock will be released on exit."mktemp und flock in einem Skript kombinieren
Robuste defensive Skripte benötigen beides: eine Sperre, um gleichzeitige Ausführungen zu verhindern, und sichere temporäre Dateien für Zwischendaten. Hier ist das vollständige Muster, das beide Techniken kombiniert:
- Erwerben Sie zuerst die Sperre — bevor Sie temporäre Dateien erstellen —, damit überhaupt nur eine Instanz Arbeit ausführt.
- Erstellen Sie temporäre Ressourcen erst, nachdem die Sperre bestätigt wurde.
- Registrieren Sie den
trapunmittelbar nach dem Erstellen der temporären Ressourcen, damit die Bereinigung unabhängig von der Art des Skriptendes garantiert ist. - Die Sperrdatei darf niemals im temporären Verzeichnis liegen — sie muss zwischen den Ausführungen bestehen bleiben, damit
flockdarauf verweisen kann.
#!/usr/bin/env bash
set -euo pipefail
LOCKFILE="/tmp/report_builder.lock"
exec 200>"$LOCKFILE"
if ! flock -n 200; then
echo "Already running — aborting." >&2
exit 1
fi
# Now safe to create temp resources
TMPDIR=$(mktemp -d /tmp/report.XXXXXX)
TMPLOG=$(mktemp /tmp/report_log.XXXXXX)
cleanup() {
rm -rf "${TMPDIR:-}"
rm -f "${TMPLOG:-}"
}
trap cleanup EXIT
echo "Building report in $TMPDIR" | tee "$TMPLOG"
echo "Step 1 complete" >> "$TMPLOG"
cat "$TMPLOG"Sperrverzeichnisse als alternativer Sperrmechanismus
Auf Systemen, auf denen flock nicht verfügbar ist (etwa auf manchen eingebetteten Systemen oder bei Netzwerkdateisystemen wie NFS), können Sie stattdessen Sperrverzeichnisse verwenden. mkdir ist auf POSIX-Systemen atomar: Der Befehl ist nur erfolgreich, wenn das Verzeichnis noch nicht existiert.
- Erstellen Sie das Sperrverzeichnis mit
mkdir /tmp/myscript.lock.d— falls eine andere Instanz es bereits erstellt hat, schlägtmkdirsofort fehl. - Speichern Sie Metadaten (etwa die PID) zu Diagnosezwecken im Verzeichnis.
- Entfernen Sie das Verzeichnis in einem
trapfürEXITimmer. - Wichtiger Hinweis: Anders als
flockwird eine Verzeichnissperre nicht automatisch freigegeben, wenn der Prozess mit-9beendet wird oder der Rechner neu startet — fügen Sie eine Prüfung auf veraltete Sperren hinzu.
#!/usr/bin/env bash
set -euo pipefail
LOCKDIR="/tmp/myscript.lock.d"
# Atomic mkdir — fails if directory already exists
if ! mkdir "$LOCKDIR" 2>/dev/null; then
# Check if the holding PID is still alive
HOLDER_PID=$(cat "$LOCKDIR/pid" 2>/dev/null || echo "")
if [[ -n "$HOLDER_PID" ]] && kill -0 "$HOLDER_PID" 2>/dev/null; then
echo "Locked by PID $HOLDER_PID. Exiting." >&2
exit 1
else
echo "Stale lock detected. Removing and continuing." >&2
rm -rf "$LOCKDIR"
mkdir "$LOCKDIR"
fi
fi
echo "$$" > "$LOCKDIR/pid"
trap 'rm -rf "$LOCKDIR"' EXIT
echo "Lock acquired via directory. Running..."
sleep 1
echo "Done."Warten mit Timeout mithilfe von flock
Manchmal möchten Sie auf eine Sperre warten, statt sofort fehlzuschlagen — aber nicht unbegrenzt lange. flock unterstützt mit der Option -w ein Timeout.
flock -w 10 200wartet bis zu 10 Sekunden auf die Sperre und wird anschließend mit Status 1 beendet, wenn sie weiterhin nicht verfügbar ist.- Dies eignet sich ideal für Skripte, die sich hinter einem kurz laufenden Vorgänger einreihen, aber aufgeben sollen, wenn der Vorgänger feststeckt.
- Kombinieren Sie
-wmit einer aussagekräftigen Fehlermeldung, die den Kontext enthält — den Pfad der Sperrdatei und die Wartezeit —, damit Betreiber hängende Prozesse schnell diagnostizieren können.
#!/usr/bin/env bash
set -euo pipefail
LOCKFILE="/tmp/data_sync.lock"
TIMEOUT=15
exec 200>"$LOCKFILE"
echo "Waiting up to ${TIMEOUT}s for lock on $LOCKFILE..."
if ! flock -w "$TIMEOUT" 200; then
echo "ERROR: Could not acquire lock after ${TIMEOUT}s." \
"Another instance may be hung." >&2
exit 1
fi
echo "Lock acquired. Syncing data..."
sleep 1
echo "Sync complete."Defensive Checkliste: Sichere temporäre Ressourcen
Bevor Sie ein Skript ausliefern, das temporäre Dateien oder Sperren verwendet, gehen Sie diese Checkliste durch:
- Verwenden Sie
mktemp, niemals fest codierte Pfade —/tmp/myapp.tmpist vorhersehbar und ausnutzbar. - Speichern Sie den Pfad sofort —
TMPFILE=$(mktemp ...)vor jedem anderen Befehl. - Registrieren Sie
trap cleanup EXITunmittelbar nach der Erstellung — nicht erst am Ende des Skripts. - Setzen Sie alle Variablenverwendungen in doppelte Anführungszeichen —
rm -f "$TMPFILE", niemalsrm -f $TMPFILE. - Bevorzugen Sie
flockgegenüber PID-Dateien — vom Kernel verwaltet und bei einem Absturz automatisch freigegeben. - Verwenden Sie standardmäßig das nicht blockierende
-n— still blockierende Sperren verbergen Leistungsprobleme. - Platzieren Sie die Sperrdatei außerhalb des temporären Verzeichnisses — damit sie den Bereinigungs-Trap überdauert.
- Testen Sie das Bereinigungsverhalten — führen Sie Ihr Skript aus und beenden Sie es während der Ausführung mit
kill -9; prüfen Sie, dass keine Dateien zurückbleiben (bei Skripten auf Basis vonflock; Verzeichnissperren erfordern besondere Sorgfalt).
Wissenscheck: Verhalten der flock-Optionen
Ein Cron-Job wird jede Minute ausgeführt und verarbeitet eine gemeinsam genutzte Datei. Sie möchten, dass jede neue Ausführung sofort mit einem Fehler beendet wird, wenn eine vorherige Ausführung noch aktiv ist, ohne zu warten. Welche flock-Invocation setzt dies korrekt um?
Zusammenfassung: Sichere temporäre Dateien und Sperrverzeichnisse
In dieser Lektion haben Sie die beiden wichtigsten Werkzeuge für die defensive Ressourcenverwaltung in Bash kennengelernt:
mktemperstellt nicht vorhersehbare temporäre Dateien (0600) und Verzeichnisse (0700) mit sicheren Berechtigungen und verhindert so Race Conditions und Symlink-Angriffe, die bei fest codierten Pfaden auftreten.trap cleanup EXITgarantiert die Entfernung temporärer Dateien bei jedem Beenden — normal, fehlerbedingt oder signalbedingt —, wenn der Trap unmittelbar nach der Erstellung registriert wird.flockstellt vom Kernel erzwungenes Advisory Locking bereit: Verwenden Sie-n, um bei einer Konkurrenzsituation sofort fehlzuschlagen,-w N, um mit Timeout zu warten, und das Musterexec 200>filefür Sperren innerhalb des Skripts, die der Kernel beim Beenden des Prozesses automatisch freigibt.- Sperrverzeichnisse (
mkdir) bieten eine portable Ausweichlösung für Umgebungen, in denenflocknicht verfügbar ist, erfordern jedoch eine explizite Erkennung veralteter Sperren. - Halten Sie die Sperrdatei immer außerhalb des temporären Verzeichnisses und setzen Sie jede bei der Bereinigung verwendete Variable in doppelte Anführungszeichen.
Die Kombination aus mktemp + flock + trap liefert Skripte, die vor gleichzeitigen Ausführungen, unvorhersehbaren Abstürzen und manipulativen Eingriffen in das Dateisystem geschützt sind.
Häufig gestellte Fragen
Ist die Lektion „Sichere temporäre Dateien und Sperrverzeichnisse“ kostenlos?
Ja — der vollständige Text von „Sichere temporäre Dateien und Sperrverzeichnisse“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des DevOps Bootcamp-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der DevOps Bootcamp-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Sichere temporäre Dateien und Sperrverzeichnisse“?
Verwenden Sie mktemp und flock, um vor Race Conditions geschützte temporäre Ressourcen zu erstellen und parallele Skriptausführungen zu verhindern. Du übst DevOps Bootcamp 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 DevOps Bootcamp zu starten?
Keine Vorkenntnisse erforderlich. DevOps Bootcamp 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 3 von 4.
Wie lange dauert die Lektion „Sichere temporäre Dateien und Sperrverzeichnisse“?
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 DevOps Bootcamp-Lektion Code schreiben und ausführen?
Ja. Jede DevOps Bootcamp-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