/tmp ist der weltweit schreibbare Sammelpfad für kurzlebige Dateien — Zwischen-Output von Kompilierungen, entpackte Archive, Editor-Swap-Files, IPC-Sockets. Auf modernen Distributionen liegt /tmp häufig als tmpfs im RAM, ist also nach jedem Reboot leer und blitzschnell. Das Sticky-Bit (Mode 1777) verhindert, dass Nutzer fremde Dateien dort löschen — der wichtigste Schutz auf einem Multi-User-System.
Was ist /tmp?
Der FHS-Standard (3.0, Kapitel 3.18) beschreibt /tmp als Pfad für temporäre Daten, auf den jeder User schreibend zugreifen darf. Drei Eigenschaften definieren das Verzeichnis:
- World-writable: jeder User kann Dateien anlegen, also Mode
1777(drwxrwxrwt). - Sticky-Bit gesetzt: trotz des
rwxfür alle dürfen User nur ihre eigenen Dateien löschen oder umbenennen. - Vergänglich: Programme dürfen nicht erwarten, dass Dateien einen Reboot überleben oder länger als nötig erhalten bleiben.
ls -ld /tmp
# drwxrwxrwt 22 root root 4096 ... /tmp
# Das 't' am Ende ist das Sticky-Bit
# Numerisch: 1777
stat -c '%a %n' /tmp
# 1777 /tmpWas typisch in /tmp landet:
- IPC-Sockets und Lock-Files von Daemons und User-Sessions (
.X11-unix/,.ICE-unix/) - Build-Artefakte von
gcc,pip,npm(während eines Compile-Laufs) - Editor-Swap- und Backup-Files von vim, emacs
- Entpackte Archive und Download-Caches
- Temp-Outputs von Shell-Skripten (
mktemplegt hier an) - Browser-Caches in manchen Konfigurationen
Sticky-Bit: world-writable, aber nicht world-deletable
Ohne Sticky-Bit könnte jeder User in einem 0777-Verzeichnis nicht nur eigene Dateien anlegen, sondern auch fremde Dateien löschen oder umbenennen — denn nur die Verzeichnis-Berechtigung zählt für unlink(). Das ist auf einem Multi-User-System natürlich gefährlich.
Das Sticky-Bit (Bit 9 der Unix-Permissions, dargestellt als t an der letzten Stelle) ändert genau diese Regel:
In einem Verzeichnis mit Sticky-Bit darf eine Datei nur vom Owner der Datei oder vom Owner des Verzeichnisses (typischerweise root) gelöscht werden — auch wenn andere User Schreibrechte auf das Verzeichnis haben.
# Sticky-Bit setzen
chmod +t /pfad/zum/dir
chmod 1777 /pfad/zum/dir # alternativ numerisch
# Sichtbar als 't' am Ende
ls -ld /pfad/zum/dir
# drwxrwxrwt 2 root root 4096 ... /pfad/zum/dir
# Großes T: rwx fehlt für andere, Sticky trotzdem gesetzt
ls -ld /pfad/restricted
# drwxrwx--T
# Sticky-Bit entfernen
chmod -t /pfadAußer /tmp haben auch /var/tmp und manche IPC-Verzeichnisse (/dev/shm, /run/lock) das Sticky-Bit. Außerhalb dieser Standard-Pfade ist es selten nötig.
tmpfs: /tmp im RAM
Auf den meisten modernen Distributionen ist /tmp als tmpfs gemountet — ein Filesystem, das vollständig im RAM lebt. Das hat mehrere Vorteile:
- Geschwindigkeit: Dateioperationen passieren auf RAM-Speed, kein Disk-I/O.
- Automatisch leer nach Reboot: RAM verliert seinen Inhalt beim Strom-Aus, kein Cleanup-Skript nötig.
- Schreibbar: anders als
/usroder/etcist tmpfs immer rw. - Größenlimit: tmpfs kann mit
size=-Option begrenzt werden — voller/tmpfüllt nicht die Disk.
mount | grep ' /tmp '
# tmpfs on /tmp type tmpfs (rw,nosuid,nodev,size=8011656k,nr_inodes=...)
# Wieviel RAM ist /tmp aktuell zugewiesen?
df -h /tmp
# tmpfs 7.6G 12K 7.6G 1% /tmp
# Kein tmpfs? /tmp liegt auf der normalen Disk
df -h / /tmp
# /dev/sda1 500G 80G 395G 17% /
# ... /tmp ← keine eigene ZeileAuf systemd-Distributionen aktiviert das Unit tmp.mount (in /usr/lib/systemd/system/tmp.mount) den tmpfs-Mount. Standardmäßig ist die Größe 50 % des RAMs — auf Systemen mit wenig RAM und großen Build-Jobs kann das zu wenig sein.
# tmpfs für /tmp aktivieren (falls noch normales Disk-Verzeichnis)
sudo systemctl enable --now tmp.mount
# Größe anpassen via Drop-In
sudo systemctl edit tmp.mount
# [Mount]
# Options=mode=1777,strictatime,nosuid,nodev,size=4G
sudo systemctl daemon-reload
sudo systemctl restart tmp.mountNicht alle Distributionen aktivieren tmpfs für /tmp standardmäßig — Debian und Ubuntu lassen es als Disk-Verzeichnis, Fedora und Arch nutzen tmpfs.
Aufräumen: systemd-tmpfiles
Selbst wenn /tmp ein tmpfs ist und beim Reboot geleert wird — auf Servern, die Wochen oder Monate ohne Neustart laufen, sammelt sich dort Müll an. Hier kommt systemd-tmpfiles ins Spiel: ein Service, der nach Regeln in /usr/lib/tmpfiles.d/ und /etc/tmpfiles.d/ aufräumt.
Standard-Regel auf den meisten Distributionen: Dateien in /tmp, die älter als 10 Tage sind, werden gelöscht (und in /var/tmp älter als 30 Tage).
# Konfigurationsdateien anschauen
cat /usr/lib/tmpfiles.d/tmp.conf
# # See tmpfiles.d(5) for details
# q /tmp 1777 root root 10d
# q /var/tmp 1777 root root 30d
# ...
# Was wäre zu tun? Trockenlauf
sudo systemd-tmpfiles --clean --dry-run
# Tatsächlich aufräumen (passiert sonst täglich automatisch)
sudo systemd-tmpfiles --clean
# Status des Cleanup-Timers
systemctl status systemd-tmpfiles-clean.timerDie Felder in einer tmpfiles-Regel: Type (q = quotaable, d = directory, f = file, …), Path, Mode, User, Group, Age. Mit eigenen Drop-Ins in /etc/tmpfiles.d/ lassen sich beliebige Aufräum-Regeln definieren.
/tmp vs /var/tmp vs $XDG_RUNTIME_DIR
Mehrere Pfade konkurrieren um „temporäre Daten" — sie haben aber jeweils eine spezifische Rolle:
| Pfad | Lebenszeit | Owner | Zweck |
|---|---|---|---|
/tmp | Bis Reboot oder ~10 Tage | World-writable, Sticky | Kurzlebig, schnelle IPC, Build-Output |
/var/tmp | Über Reboots hinweg, ~30 Tage | World-writable, Sticky | Persistente Temp-Daten (Editor-Recovery, Pakete) |
$XDG_RUNTIME_DIR (/run/user/<uid>/) | Bis Logout | Pro User exklusiv (0700) | User-Session-Daten, Sockets, PID-Files |
/dev/shm | Bis Reboot | World-writable, Sticky | Shared-Memory zwischen Prozessen (POSIX shm) |
Die Faustregeln:
- Für Skripte und Build-Tools:
mktempohne Argumente legt unter/tmpan. Wenn die Datei einen Reboot überstehen muss:mktemp --tmpdir=/var/tmpoder viaTMPDIR=/var/tmp mktemp. - Für User-Sessions:
$XDG_RUNTIME_DIRist die richtige Wahl. Sockets, PID-Files, kurzfristige Caches gehören dort hin. - Für Shared Memory zwischen Prozessen:
/dev/shmist die POSIX-Standard-Schnittstelle fürshm_open().
# Sichere Temp-Datei (eindeutig, nur für aktuellen User lesbar)
TMPFILE=$(mktemp)
trap "rm -f $TMPFILE" EXIT
echo "data" > "$TMPFILE"
# Mit Prefix für Lesbarkeit
TMPFILE=$(mktemp -t myapp-XXXXXX)
# Verzeichnis statt Datei
TMPDIR=$(mktemp -d)
trap "rm -rf $TMPDIR" EXIT
# In /var/tmp statt /tmp
TMPFILE=$(mktemp --tmpdir=/var/tmp)
# In XDG_RUNTIME_DIR (User-Session-Scope)
TMPFILE=$(mktemp -p "$XDG_RUNTIME_DIR")Wichtig: niemals einen Pfad wie /tmp/myfile.tmp hartkodieren. Das ist ein klassisches Race-Condition-Risiko (zwei Skripte schreiben gleichzeitig in dieselbe Datei) und ein Sicherheits-Problem (Angreifer kann via Symlink-Attack steuern, wo gelandet wird). mktemp löst beides.
Mount-Optionen für /tmp: nosuid, nodev, noexec
Sicherheits-Praxis: /tmp sollte mit nosuid,nodev,noexec gemountet sein. Das verhindert klassische Privilege-Escalation-Vektoren:
| Option | Wirkung |
|---|---|
nosuid | SUID-Bit auf Dateien wird ignoriert — kein Root-Hack via dort abgelegtes Binary |
nodev | Device-Nodes werden nicht respektiert — Schutz gegen /tmp/sda als Disk-Zugriff |
noexec | Dateien sind nicht ausführbar — Angreifer kann kein Binary einschleusen und starten |
Beim systemd-tmpfs sind die ersten beiden Optionen Default, noexec aber nicht — viele Build-Tools und Skripte erwarten, dass /tmp ausführbare Skripte halten kann (apt-get extrahiert .deb-Pakete dorthin, npm baut native Module).
Wer die Sicherheit aufdreht, riskiert, dass Tools brechen. Für besonders gehärtete Setups: noexec setzen, im Zweifel mit TMPDIR=/var/tmp oder ~/.local/tmp arbeiten.
mount | grep ' /tmp '
# tmpfs on /tmp type tmpfs (rw,nosuid,nodev,size=4G,nr_inodes=...)
# Aktive Sicherheits-Hardening-Tests
sudo lynis audit system | grep -i tmpInteressantes
/tmp ist nicht der Ort für wichtige Daten
Klassischer Anfänger-Fehler: ein Backup nach /tmp legen und sich wundern, warum es nach dem Reboot weg ist. Auch beim Editieren mit vim: das Original-File ist nicht in /tmp, aber das Recovery-File .swp schon — bei einem Crash ist es weg, wenn /tmp ein tmpfs ist. Für persistente Temp-Daten gehört es nach /var/tmp oder ~/.cache/.
Volle /tmp ist auf Build-Servern eine Standard-Plage
apt-get, dnf, npm, cargo, große Compiler — alle entpacken oder bauen in /tmp. Wer Container baut oder npm-Module kompiliert, kann mit 1 GB tmpfs schnell aus dem Speicher fallen. Lösung: tmpfs-Größe in tmp.mount auf 4 GB oder mehr setzen, oder TMPDIR=/var/tmp für ein konkretes Tool exportieren.
Sticky-Bit funktioniert auch ohne world-writable
+t lässt sich auch auf 0750-Verzeichnissen setzen — dann gilt: nur die Gruppen-Mitglieder dürfen schreiben, und auch sie können nur ihre eigenen Dateien löschen. Für Group-Drop-Boxes ist das ein praktisches Pattern.
systemd-tmpfiles räumt mehr als nur /tmp auf
Die Regeln in /usr/lib/tmpfiles.d/ decken auch /var/cache/, /run/, App-State unter /var/lib/<service> und vieles mehr ab. Ein eigener Service kann seine eigenen Aufräum-Regeln definieren (z. B. „Logs älter als 7 Tage in /var/log/myapp/ löschen") — das ist meist sauberer als ein Cron-Job.
Auf Containern ist /tmp oft tiny
Standard-Container-Images haben /tmp als ein normales Verzeichnis im Image-Layer — kein tmpfs, keine Größenlimits, aber auch geschrieben in den Container-Layer (was beim Commit oder Backup mitwandert). Wer im Container temporäre Dateien anlegt, sollte /tmp als Volume-Mount einrichten oder das Programm via TMPDIR=/dev/shm umlenken.
$XDG_RUNTIME_DIR ist die richtige Wahl für User-Sockets
PulseAudio, dbus, GnuPG-Agent legen ihre Sockets unter /run/user/<uid>/ ab — automatisch beim Login angelegt, automatisch beim Logout entlassen. Das ist eleganter als /tmp/<uid>/, weil keine Cleanup-Logik nötig ist und der Pfad nur dem aktuellen User gehört (mode=0700).
Weiterführende Ressourcen
Externe Quellen
- Filesystem Hierarchy Standard 3.0 — /tmp
- systemd-tmpfiles Documentation
- tmpfiles.d(5) — Format der Aufräum-Regeln
- mktemp(1) — sichere Temp-Files anlegen
- XDG Base Directory Specification