Layer 8Ehrlicher Tech-Support
BetriebssystemSchweregrad: Lästig

Linux: systemd-Timer holt verpasste Läufe nicht nach

Der systemd-Timer lief nachts nicht, weil der Rechner aus war, und holt nichts nach? Persistent= steht auf false, solange man es nicht setzt.

Aufwand:
ca. 15 Min.
Voraussetzung:
systemctl, Editor für die Timer-Unit, Handbuchseite systemd.timer(5)
Gilt für:
Linux mit systemd (systemd.timer(5), Handbuchseite in der am 2026-10-15 abrufbaren Fassung), Timer mit OnCalendar=; für monotone Timer (OnBootSec=, OnUnitActiveSec=) gilt die Option nicht

Das Symptom

Ein Backup-Timer mit OnCalendar=daily oder ein wöchentlicher Aufräumjob steht auf einem Laptop oder einem Rechner, der nachts aus ist. Der Nutzer geht davon aus, dass systemd den verpassten Zeitpunkt beim nächsten Einschalten nachholt, so wie er es von anacron kennt oder schlicht erwartet. Tatsächlich passiert nichts: systemctl list-timers zeigt den nächsten geplanten Zeitpunkt, der wieder in der Nacht liegt, und das Backup läuft wochenlang nie. Weil der Timer selbst aktiv ist und kein Dienst auf failed steht, fällt der Ausfall erst auf, wenn man die Sicherung braucht.

Die „Layer 8“-Wahrheit

Die Handbuchseite systemd.timer(5) macht das Nachholen zu einer ausdrücklichen Option. Persistent= „Takes a boolean argument. If true, the time when the service unit was last triggered is stored on disk. When the timer is activated, the service unit is triggered immediately if it would have been triggered at least once during the time when the timer was inactive. Such triggering is nonetheless subject to the delay imposed by RandomizedDelaySec=.“ Die Seite nennt genau den Anwendungsfall: „This is useful to catch up on missed runs of the service when the system was powered down.“ Und sie schließt mit dem Satz, der das Symptom erklärt: „Defaults to false.“ Ohne diese Zeile in der Sektion [Timer] holt systemd also nichts nach. Es ist keine Fehlfunktion, sondern die Voreinstellung.

Zwei Einschränkungen stehen ebenfalls dort. Erstens: „Note that this setting only has an effect on timers configured with OnCalendar=.“ Monotone Timer wie OnBootSec= oder OnUnitActiveSec= rechnen ab dem Systemstart oder ab dem letzten Lauf, für sie ändert die Option nichts, und ein Rechner, der täglich neu startet, beginnt ihren Zeitraum jedes Mal von vorn. Zweitens unterliegt das Nachholen weiterhin der Verzögerung aus RandomizedDelaySec=, sodass der nachgeholte Lauf nicht in derselben Sekunde starten muss. Wer die gespeicherte Marke loswerden will, nutzt laut Seite systemctl clean –what=state auf der Timer-Unit.

Die Erwartung, dass nachgeholt wird, stammt aus einer anderen Welt: anacron wurde genau dafür gebaut, Rechner zu versorgen, die nicht durchlaufen, und viele Nutzer halten jeden Zeitplaner für so gebaut. systemd trennt die beiden Fragen bewusst. Ob ein Termin verpasst werden darf, entscheidet die Unit, nicht der Zeitplaner, und die Antwort lautet so lange ja, bis jemand Persistent=true hineinschreibt. Auf einem Server, der nie ausgeht, merkt man den Unterschied nie. Auf einem Laptop merkt man ihn an dem Tag, an dem man die Sicherung braucht.

Ein Nebeneffekt verdient Erwähnung: Mit Persistent=true läuft der Dienst nach jedem längeren Ausschalten genau einmal nach, nicht für jede verpasste Fälligkeit einzeln. Wer eine Woche im Urlaub war, bekommt beim ersten Start ein Backup, nicht sieben. Für Sicherungen ist das genau richtig; für Aufgaben, die auf jeden Tag einzeln angewiesen sind, etwa das Rotieren von Logdateien mit Datum, muss der Dienst selbst nachsehen, was er versäumt hat.

Die echte, verifizierte Lösung

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

  1. 1.

    Nachsehen, wann der Dienst zuletzt wirklich lief

    systemctl list-timers --all zeigt je Timer die Spalten NEXT und LAST. Steht unter LAST n/a oder ein Zeitpunkt von vor Wochen, obwohl der Timer täglich auslösen soll, wurde nichts nachgeholt. Der Timer selbst meldet keinen Fehler, deshalb ist diese Liste die einzige Stelle, an der der Ausfall vor dem Ernstfall sichtbar wird.

    systemctl list-timers --all
    
  2. 2.

    Persistent=true in die Timer-Unit eintragen

    In der Datei der Timer-Unit unter [Timer] die Zeile Persistent=true ergänzen. Sie wirkt nur bei Timern mit OnCalendar=. Bei Units aus Paketen den Drop-in-Weg nehmen, damit das nächste Update die Änderung nicht überschreibt: systemctl edit name.timer öffnet eine Überlagerungsdatei, in die nur die Sektion und die Zeile gehören.

    [Timer]
    OnCalendar=daily
    Persistent=true
    
  3. 3.

    Konfiguration neu laden und den Timer neu starten

    Nach der Änderung systemctl daemon-reload ausführen und den Timer neu starten. Ab dann speichert systemd den Zeitpunkt des letzten Auslösens, und beim nächsten Einschalten nach einer verpassten Fälligkeit startet der Dienst sofort. Zur Kontrolle nach dem nächsten Neustart wieder list-timers lesen; LAST sollte dann den Startzeitpunkt zeigen.

    sudo systemctl daemon-reload
    sudo systemctl restart name.timer
    
  4. 4.

    Mit der zufälligen Verzögerung rechnen

    Steht RandomizedDelaySec= in der Unit, läuft der nachgeholte Dienst nicht zwingend in derselben Sekunde, sondern irgendwann innerhalb der Spanne. Wer das nicht will, setzt die Spanne für diesen Timer herab oder auf 0; wer viele Timer hat, lässt sie, denn die Verzögerung ist dazu da, dass nicht alles gleichzeitig startet.

  5. 5.

    Monotone Timer gesondert prüfen

    Für Timer mit OnBootSec= oder OnUnitActiveSec= greift Persistent= nicht. Sie messen ab dem Systemstart oder ab dem letzten Lauf, und bei einem Rechner, der jeden Tag neu startet, beginnt der Zeitraum jedes Mal von vorn. Wer tägliche Sicherungen will, baut den Timer auf OnCalendar= um und setzt dann Persistent=true.

Häufige Fragen (FAQ)

?Der Timer ist aktiv und kein Dienst steht auf failed. Warum lief das Backup trotzdem nie?

Weil ein Timer, dessen Zeitpunkt im ausgeschalteten Zustand verstreicht, nach dem Einschalten einfach den nächsten Zeitpunkt berechnet. Die Handbuchseite systemd.timer(5) macht das Nachholen zu einer ausdrücklichen Option namens Persistent= und schließt deren Beschreibung mit „Defaults to false“. Ohne diese Zeile in der Timer-Unit holt systemd nichts nach. Der Timer ist dabei aus seiner Sicht gesund: Er wartet auf den nächsten Termin, der wieder nachts liegt, und das Backup läuft wochenlang nie.

?Was genau macht Persistent=true?

Nach systemd.timer(5): „If true, the time when the service unit was last triggered is stored on disk. When the timer is activated, the service unit is triggered immediately if it would have been triggered at least once during the time when the timer was inactive. Such triggering is nonetheless subject to the delay imposed by RandomizedDelaySec=.“ Die Seite nennt den Anwendungsfall selbst: „This is useful to catch up on missed runs of the service when the system was powered down.“ Beim nächsten Start nach einer verpassten Fälligkeit startet der Dienst also sofort, einmal, nicht für jede verpasste Nacht einzeln.

?Gilt das für jeden Timer?

Nein. Die Handbuchseite schränkt ein: „Note that this setting only has an effect on timers configured with OnCalendar=.“ Monotone Timer wie OnBootSec= oder OnUnitActiveSec= rechnen ab dem Systemstart oder ab dem letzten Lauf und brauchen die Option nicht; für sie ändert Persistent= nichts. Wer einen Backup-Timer mit OnUnitActiveSec=1d gebaut hat, hat ein anderes Problem, nämlich dass der Zeitraum mit jedem Neustart neu beginnt.

?Warum startet der nachgeholte Lauf nicht sofort in derselben Sekunde?

Weil RandomizedDelaySec= weiter gilt, wenn es gesetzt ist. Viele Distributionen liefern Timer mit einer zufälligen Verzögerung aus, damit nicht alle Jobs gleichzeitig starten; der nachgeholte Lauf unterliegt derselben Verzögerung. Wer nach dem Einschalten sofort ein Ergebnis erwartet, wartet die eingestellte Spanne ab oder prüft mit systemctl list-timers, wann der Lauf geplant ist. Wer die gespeicherte Zeitmarke loswerden will, nutzt laut Handbuchseite systemctl clean --what=state auf der Timer-Unit.

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ästigcommand not found

cron-Job läuft nicht (leeres PATH)

cron führt deinen Job nicht aus oder meldet 'command not found'? cron startet mit fast leerem PATH. So findet der Job seine Programme wieder.

OSLästigOut of memory: Killed process

Linux: Prozess wurde vom OOM-Killer beendet

Ein Dienst verschwindet ohne Absturzmeldung? Bei Speichermangel beendet der Kernel selbst Prozesse. Das Protokoll verrät, wen es traf und warum.