Layer 8Ehrlicher Tech-Support
BetriebssystemSchweregrad: Lästig

Linux: Dateien in /tmp verschwinden ohne Neustart

Ein Skript legt Arbeitsdaten in /tmp ab, Tage später sind sie weg, obwohl niemand gelöscht hat. systemd-tmpfiles räumt nach Alter auf, planmäßig.

Aufwand:
ca. 15 Min.
Voraussetzung:
Ein Terminal mit Root-Rechten oder sudo, systemd mit systemd-tmpfiles und tmpfiles.d-Konfiguration, Ein Editor für eine Datei unter /etc/tmpfiles.d/
Gilt für:
Linux mit systemd laut Handbuchseiten tmpfiles.d(5) und systemd-tmpfiles(8) in der Fassung systemd 262~devel auf man7.org (abgerufen 17.10.2026); lokale Beobachtungen auf einem Fedora-System

Das Symptom

Ein Datenimport läuft über mehrere Tage. Das Skript legt seine Zwischenstände in /tmp ab, wo sie nicht stören und wo jeder schreiben darf. Am Montag fehlt die Hälfte der Dateien. Der Rechner lief durch, niemand hat rm aufgerufen, und die Dateien eines Kollegen vom Freitag liegen noch da. Es sieht nach einem defekten Dateisystem aus oder nach einem Kollegen mit schlechtem Gewissen.

Die zweite Variante trifft Entwickler: Ein Dienst schreibt seine Sperrdatei oder seinen Unix-Socket nach /tmp und läuft wochenlang stabil. Dann ist der Socket plötzlich weg, obwohl der Prozess noch lebt, und Verbindungen schlagen fehl. Neustart hilft, und der Fehler wird als Laune des Systems abgelegt.

Die „Layer 8“-Wahrheit

Es gibt einen Aufräumdienst, und er tut, was in seiner Konfiguration steht. tmpfiles.d(5) beschreibt den Zweck des Mechanismus als Anlegen von Dateien und Verzeichnissen, Anpassen ihrer Rechte „and finally their time-based removal“. Die Zeile, die /tmp regelt, lag auf dem Prüfsystem in /usr/lib/tmpfiles.d/tmp.conf und lautete q /tmp 1777 root root 10d. Das letzte Feld ist das Alter: Was älter als zehn Tage ist, wird entfernt. Die Handbuchseite formuliert die Regel ohne Ausnahme: „If a file or directory is older than the current time minus the age field, it is deleted.“

Dass es ohne Neustart passiert, liegt am Timer. systemd-tmpfiles(8) nennt systemd-tmpfiles-clean.service und systemd-tmpfiles-clean.timer als Systemeinheiten; der Timer auf dem Prüfsystem startete den Dienst eine Viertelstunde nach dem Boot und danach täglich. Ein Server mit 400 Tagen Laufzeit hat die Bereinigung also rund 400 Mal ausgeführt. Dass die Datei des Kollegen vom Freitag noch da ist, widerspricht dem nicht: Sie war schlicht noch keine zehn Tage alt.

Was als Alter zählt, ist der Teil, an dem die meisten Annahmen scheitern. Die Handbuchseite nennt drei Zeitstempel, mtime, atime und bei Dateien auch ctime, und jeder davon hält die Datei am Leben, solange er jung genug ist. Der Zugriffsstempel ist dabei der unzuverlässigste, weil er davon abhängt, wie das Dateisystem eingehängt ist. Der Importlauf, der eine Datei vor zwölf Tagen geschrieben und seither nur gelesen hat, kann deshalb genau in die Lücke fallen. Bei Verzeichnissen wird der ctime laut Handbuchseite absichtlich nicht beachtet, weil das Löschen von Dateien darin den ctime des Verzeichnisses ändert und die Bereinigung sich sonst selbst verjüngen würde.

Für laufende Programme gibt es eine Ausnahme, die zum Design gehört: Die Bereinigung nimmt auf jedem Eintrag, den sie löschen will, eine BSD-Dateisperre, und was bereits gesperrt ist, wird samt Inhalt übersprungen. Ein Dienst, der sein Verzeichnis unter /tmp per flock hält, ist geschützt, solange er läuft. Der Socket aus dem zweiten Symptom war nicht gesperrt und älter als zehn Tage, also weg, obwohl der Prozess noch lief. Der Zeitstempel einer Socket-Datei ändert sich durch Verbindungen nicht zwingend; die Datei liegt da und altert.

Der Ausweg ist einfacher als die Diagnose. Wer eine Ausnahme braucht, schreibt sie als x-Zeile nach /etc/tmpfiles.d/, wo laut Handbuchseite die Dateien des lokalen Administrators liegen und gleichnamige Paketdateien überschreiben. Wer ein anderes Alter für /tmp will, legt dort eine eigene tmp.conf an. Und wer Daten länger als zehn Tage braucht, legt sie nicht in ein Verzeichnis, dessen Hausordnung im Namen steht.

Die echte, verifizierte Lösung

1000 % faktenbasiert. Jeder Befehl ist real, jeder Pfad existiert. Schritt für Schritt:

  1. 1.

    Die geltende Regel für /tmp finden

    Die Konfiguration liegt in Dateien unter /usr/lib/tmpfiles.d/, /run/tmpfiles.d/ und /etc/tmpfiles.d/. Laut tmpfiles.d(5) installieren Pakete ihre Dateien unter /usr/lib/tmpfiles.d, und Dateien in /etc/tmpfiles.d überschreiben gleichnamige Dateien in den beiden anderen Verzeichnissen. Die Suche nach /tmp zeigt die Zeile mit dem Altersfeld. Auf dem Prüfsystem lautete sie q /tmp 1777 root root 10d: Typ q, Pfad, Rechte 1777, Eigentümer root, Gruppe root, Alter zehn Tage. Das Altersfeld gilt laut Handbuchseite nur für die Typen d, D, e, v, q, Q, C, r, R, x und X; steht dort ein Strich, wird nicht aufgeräumt.

    grep -rn '/tmp' /usr/lib/tmpfiles.d/ /run/tmpfiles.d/ /etc/tmpfiles.d/ 2>/dev/null
    
  2. 2.

    Den Zeitplan der Bereinigung lesen

    systemd-tmpfiles(8) führt systemd-tmpfiles-clean.service und systemd-tmpfiles-clean.timer als Systemeinheiten auf. Der Timer bestimmt, wann der Dienst läuft; seine Einstellungen stehen in der Unit-Datei und nicht in der Handbuchseite. Auf dem Prüfsystem enthielt der Timer OnBootSec=15min und OnUnitActiveSec=1d, also ein Lauf eine Viertelstunde nach dem Start und danach einmal täglich. Bei einem Rechner, der nie neu gestartet wird, läuft die Bereinigung also trotzdem jeden Tag, was die Beobachtung erklärt, dass Dateien ohne Neustart verschwinden.

    systemctl cat systemd-tmpfiles-clean.timer
    systemctl list-timers systemd-tmpfiles-clean.timer
    
  3. 3.

    Vorab ansehen, was gelöscht würde

    Bevor man die Konfiguration ändert, hilft ein Blick, wie das Werkzeug die aktuelle Lage beurteilt. systemd-tmpfiles(8) beschreibt den Befehl --clean so: „If this command is passed, all files and directories with an age parameter configured will be cleaned up.“ Zusammen mit --dry-run führt das Werkzeug nichts aus, sondern zeigt nur an, was es täte. Das Ergebnis zeigt, welche Dateien die Altersgrenze bereits überschritten haben. Ohne --dry-run wird tatsächlich gelöscht, deshalb den Schalter erst entfernen, wenn das gewollt ist.

    sudo systemd-tmpfiles --dry-run --clean
    
  4. 4.

    Eigene Ausnahme oder eigenes Alter setzen

    Wer einen Pfad in /tmp dauerhaft von der Bereinigung ausnehmen will, legt eine eigene Datei unter /etc/tmpfiles.d/ an. Eine Zeile vom Typ x schließt laut tmpfiles.d(5) einen Pfad samt Inhalt von der Bereinigung aus, Typ X nur das Verzeichnis selbst, nicht dessen Inhalt; beide akzeptieren Shell-Globs. Soll stattdessen das Alter für /tmp insgesamt anders sein, legt man eine Datei mit demselben Namen wie die Paketdatei an, also tmp.conf, und trägt die Zeile mit dem gewünschten Alter ein; laut Handbuchseite überschreibt die Datei in /etc/tmpfiles.d dann die gleichnamige in /usr/lib/tmpfiles.d. Nach der Änderung reicht laut systemd-tmpfiles(8) ein Neustart von systemd-tmpfiles-clean.service, um die Einstellungen neu anzuwenden.

    # /etc/tmpfiles.d/mein-import.conf
    x /tmp/mein-import
    
  5. 5.

    Den Ablageort ehrlich wählen

    Die eigentliche Korrektur ist meist keine Konfigurationsänderung, sondern eine Entscheidung: Was länger als die konfigurierte Frist gebraucht wird, gehört nicht nach /tmp. tmpfiles.d(5) beschreibt den Mechanismus ausdrücklich als für flüchtige und temporäre Dateien gedacht, mit /run/, /tmp/ und /var/tmp/ als typischen Orten. Für Dienste empfiehlt die Handbuchseite RuntimeDirectory=, StateDirectory= und CacheDirectory= in der Unit-Datei, womit die Lebensdauer eines Verzeichnisses an den Dienst gebunden ist. Ein Import, der eine Woche braucht, und ein Zwischenstand, den man nächsten Monat noch braucht, gehören in ein Verzeichnis, das man selbst aufräumt.

Häufige Fragen (FAQ)

?Wer löscht die Dateien, wenn niemand löscht?

systemd-tmpfiles. Die Handbuchseite tmpfiles.d(5) beschreibt den Mechanismus so: „systemd-tmpfiles(8) uses this configuration to create volatile files and directories during boot and to do periodic cleanup afterwards.“ Für /tmp gibt es üblicherweise eine Konfigurationszeile mit einem Altersfeld, und der Dienst systemd-tmpfiles-clean.service, gestartet von systemd-tmpfiles-clean.timer, entfernt alles, was älter ist. Das geschieht im laufenden Betrieb, nicht nur beim Neustart. Auf dem System, auf dem dieser Eintrag geprüft wurde, stand in /usr/lib/tmpfiles.d/tmp.conf für /tmp ein Alter von 10d und für /var/tmp 30d.

?Die Datei wurde doch gestern noch gelesen, warum ist sie trotzdem weg?

Weil nicht nur das Lesen zählt, sondern die Zeitstempel, die das Dateisystem tatsächlich führt. tmpfiles.d(5) sagt: „The age of a file system entry is determined from its last modification timestamp (mtime), its last access timestamp (atime), and (except for directories) its last status change timestamp (ctime).“ Standardmäßig verhindert jeder dieser Stempel das Löschen, wenn er jünger ist als jetzt minus Alter. Ist das Dateisystem aber mit einer Einhängeoption eingebunden, die den Zugriffsstempel nicht bei jedem Lesen aktualisiert, hält ein bloßes Lesen die Datei nicht sicher jung. Verlässlich ist nur, was die Datei ändert, oder ein eigener Ausschluss in der Konfiguration.

?Warum werden auch Verzeichnisse gelöscht, in denen noch Dateien lagen?

Die Aufräumlogik läuft über die Einträge unterhalb des konfigurierten Pfads, und ein Verzeichnis wird dabei nach seinen eigenen Zeitstempeln beurteilt. tmpfiles.d(5) erklärt, warum für Verzeichnisse der ctime absichtlich ignoriert wird: Die Aufräumlogik selbst ändert den ctime, sobald sie eine Datei darin löscht, und das soll nicht in die nächste Runde zurückwirken. Die Voreinstellung für die herangezogenen Stempel lautet laut Handbuchseite abcmABM. Wer ein ganzes Arbeitsverzeichnis schützen will, legt es deshalb nicht in /tmp an oder nimmt es mit einer x-Zeile aus der Bereinigung heraus.

?Kann ich die Löschung für mein Programm verhindern, ohne die Systemkonfiguration anzufassen?

Ja, über eine Dateisperre. tmpfiles.d(5) beschreibt, dass die Aufräumlogik auf jedem zu löschenden Eintrag eine exklusive BSD-Sperre nimmt und Einträge überspringt, auf denen bereits eine Sperre liegt: „If the aging algorithm finds a lock (shared or exclusive) is already taken on some directory/file, it (and everything below it) is skipped.“ Ein Programm, das sein Verzeichnis mit flock hält, ist also so lange geschützt, wie es läuft; endet der Prozess, fällt die Sperre, und die Bereinigung greift wieder. Das ist für Dienste gedacht, nicht für einen Ablageort, an den man sich in drei Wochen erinnern will.

?Gilt die Bereinigung auch für Dateien, die ein normaler Benutzer angelegt hat?

Ja. systemd-tmpfiles(8) unterscheidet zwischen der Systeminstanz, die die vom Administrator kontrollierten Dateien in tmpfiles.d liest, und Benutzerinstanzen, die eigene Dateien unter ~/.config/user-tmpfiles.d/ lesen. Die Handbuchseite stellt klar, dass die Systeminstanz die globale Bereinigung durchführt und von Benutzerkonfiguration nicht beeinflusst wird: Eine zeitbasierte Bereinigung, wie sie typischerweise für /tmp/ konfiguriert ist, trifft deshalb auch Dateien der Benutzerinstanz, wenn sie in /tmp/ liegen, selbst wenn deren eigene Bereinigung abgeschaltet ist. Wessen Datei es ist, spielt für den Timer keine Rolle.

Belege

Diese Seite ist gegen die folgenden Primärquellen geprüft – Hersteller, Standard oder Gesetzestext. Wer es nicht glaubt, muss es nicht: Da steht, wo es nachzulesen ist.

Zuletzt geprüft am . Dokumentation altert – ein Datum daneben ist der einzige ehrliche Umgang damit.

Auch zu finden unter

Verwandte Fehler

OSLästigPermission denied

Permission denied, obwohl man root ist

Selbst als root verweigert das System den Zugriff. Meist ist das Dateisystem schreibgeschützt eingehängt oder die Datei ist unveränderlich.