- systemd-Timer sind ein praktischer Ersatz für
cron: Sie führen Units wie .service nach Zeitplan aus und machen Verlauf, Ausgabe und Umgebungsverwaltung klarer nachvollziehbar.
- Traditionelles
cron hat Schwächen wie ein mehrdeutiges $PATH, leicht verlorenes stdout/stderr, schwer nachzuverfolgende Ausführungshistorien und eine schlecht lesbare Zeitplan-Syntax.
- Timer verknüpfen eine
.timer- und .service-Datei mit demselben Stammnamen und drücken zeit- oder ereignisbasierte Ausführung mit OnCalendar, OnBootSec und OnUnitActiveSec aus.
- Mit
systemd-analyze calendar und systemctl list-timers lassen sich Zeitangaben und der nächste Ausführungszeitpunkt prüfen; WakeSystem= kann die Ausführung sogar aus dem Ruhezustand heraus aufwecken.
RandomizedOffsetSec und FixedRandomDelay= reduzieren gleichzeitige Lastspitzen, und Persistent= holt verpasste Läufe direkt nach dem Wieder-Online-Gehen nach.
Warum man systemd-Timer als Ersatz für cron verwendet
- Der Begriff
cron job wird allgemein verwendet, um einen grundlegenden Computing-Baustein zu bezeichnen, der Aufgaben nach einem Zeitplan ausführt — etwa „führe das jeden Tag aus“ oder „führe jenes jeden Monat aus“ — auch wenn nicht der eigentliche cron-Daemon dahintersteht.
- Ein systemd-Timer ist eine systemd-Unit, die nach einem bestimmten Zeitplan eine andere Unit ausführt, meist eine
.service, und kann ein funktionaler Ersatz für den traditionellen cron-Daemon sein.
- Traditionelles
cron hat einige praktische Schwächen:
- Wegen einer mehrdeutigen
$PATH-Konfiguration ist das Ergebnis der Skriptausführung schwer vorherzusagen.
stdout- und stderr-Ausgaben verschwinden oft im Nirgendwo oder werden an das Mailsystem des Hosts geschickt.
- Die Ausführungshistorie ist schwer nachzuverfolgen und abzufragen.
- Eine Zeitplan-Syntax wie
01,31 04,05 1-15 1,6 * ist für Menschen weder gut lesbar noch intuitiv.
- systemd-Timer mindern diese Probleme und bieten zugleich Kalendereinstellungen, die
cron-artigen Ausdrücken ähneln.
Grundstruktur: Service und Timer
- Ein systemd-Timer braucht ein Ausführungsziel, und eine
.service-Unit kann logisch wie ein Skript betrachtet werden.
- Legt man zum Beispiel unter
/etc/systemd/system/roulette.service die folgende Unit ab, installiert man einen Service, der den Computer mit einer Wahrscheinlichkeit von eins zu zehn herunterfährt.
[Unit]
Description=1 in 10 chance to break your chains
[Service]
ExecStart=/usr/bin/env bash -c '[[ $(($RANDOM % 10)) == 0 ]] && systemctl poweroff || echo LIVE ANOTHER DAY'
ExecCondition= ist eine stärker integrierte Art, bedingte Ausführung als systemd-Service-Option auszudrücken, und macht auf Unit-Ebene klarer sichtbar: „Soll weiter ausgeführt werden?“
[Unit]
Description=1 in 10 chance to break your chains
[Service]
ExecCondition=/run/current-system/sw/bin/bash -c '[[ $(($RANDOM % 10)) == 0 ]]'
ExecStart=/run/current-system/sw/bin/systemctl poweroff
- Wenn die Bedingung nicht erfüllt ist, erscheint im Journal eine klarere Meldung.
May 05 11:05:32 diesel systemd[3117]: Condition check resulted in 1 in 10 chance to break your chains being skipped.
- Generell ist es oft angenehmer, die von systemd bereitgestellten Optionen zu nutzen, statt selbst zu skripten.
OnFailure= kann verwendet werden, um auf fehlschlagende Service-Skripte zu reagieren.
Restart= kann verwendet werden, um bei vorübergehenden Fehlern eine Wiederherstellung zu versuchen.
Verknüpfen und Ausführen von Timer-Units
- Legt man
/etc/systemd/system/roulette.timer mit demselben Dateistamm an, kann man den Timer mit roulette.service verknüpfen.
[Unit]
Description=impending destruction
[Timer]
OnCalendar=10:00
[Install]
WantedBy=timers.target
- Standardmäßig wählt die
Unit=-Einstellung des Timers die Service-Unit mit demselben Stammnamen und der Endung .service.
- In diesem Beispiel wird
roulette.service gewählt.
- Soll eine Service-Unit mit anderem Namen ausgeführt werden, kann
Unit= geändert werden.
- Das Ziel von
ExecStart= wird standardmäßig nicht als Shell-Befehl ausgeführt.
- Ein Ziel mit absolutem Pfad muss als Skript oder als Interpreter behandelt werden, der ein Skript als String-Argument erwartet.
ExecStart=/usr/bin/echo Hello | /usr/bin/awk funktioniert in diesem Kontext nicht, weil die Pipe hier keine Bedeutung hat.
ExecStart=-Argumente erben standardmäßig keine Umgebungsvariablen außer einigen Vorgaben des Systemmanagers.
- Das Standard-
$PATH ist fast leer.
- Das Ausführen von
/usr/bin/env ist eine einfache Schutzmaßnahme, damit Dinge wie systemctl verfügbar sind.
- Selbst wenn
ExecStart=/usr/bin/bash allein ein Standard-$PATH mitbringen würde, ist die Verwendung von env eine zusätzliche Absicherung.
- Ein Service kann auch direkt ohne Timer ausgeführt werden.
systemctl start roulette
- Ein Service ohne
[Install]-Abschnitt kann nicht mit enable aktiviert werden; in dieser Struktur ist der Timer der Standardweg, um den Service konsistent auszuführen.
systemctl arbeitet standardmäßig mit roulette.service, auch wenn kein explizites Suffix angegeben wird.
- Wenn man
systemctl start auf eine .timer-Unit anwendet, wird der Timer aktiv, aber der eigentliche mit Unit= angegebene Service wird nicht sofort ausgeführt.
systemctl start roulette.timer
status zeigt an, wann der Timer das nächste Mal ausführt.
systemctl status roulette.timer
Trigger: Sat 2026-04-18 10:00:00 MDT; 35min left
- Der einfachste Ablauf ist: den auszuführenden Service anlegen, einen Timer mit Zeitplan am selben Ort ablegen und dann den Timer statt des Ziels starten.
- Wenn der
[Install]-Abschnitt der Timer-Unit WantedBy= enthält, kann der Timer auch beim Booten automatisch hochkommen.
systemctl enable roulette.timer
Zeitausdrücke: Kalenderereignisse und Zeitspannen
- Bei Timern ist wichtig, wie Zeitpläne ausgedrückt werden: Man sollte zwischen wiederkehrenden Zeitintervallen und Kalenderereignissen oder Zeitstempeln unterscheiden.
- Die Handbuchseite
systemd.time(7) enthält genügend Beispiele und ist eine gute erste Referenz beim Schreiben von Timern.
systemd-analyze kann Zeitausdrücke prüfen und erläutern.
systemd-analyze calendar '*-*-* *:*:*'
Normalized form: *-*-* *:*:*
Next elapse: Sat 2026-04-18 16:44:26 MDT
(in UTC): Sat 2026-04-18 22:44:26 UTC
From now: 431ms left
- systemd-Timer können nicht nur wiederkehrende Wanduhrzeiten definieren, sondern im Unterschied zu traditionellem
cron auch wiederkehrende Zeitspannen relativ zu einem früheren Ereignis.
- Die vollständige Form von
daily bedeutet: jedes Jahr, jeden Monat, jeden Tag um 00:00:00 ausführen.
*-*-* 00:00:00
│ │ │ │ │ ╰── at second 00
│ │ │ │ ╰───── at minute 00
│ │ │ ╰──────── at hour 00
│ │ ╰────────── every day
│ ╰──────────── every month
╰────────────── every year
- Man kann Kurzformen wie
daily, die vollständige Form und andere von systemd.time(7) unterstützte Werte verwenden und seine Annahmen mit systemd-analyze überprüfen.
Wenn ereignisbasierte Ausführung besser passt
- In der Praxis passt „nach einem anderen Ereignis ausführen“ oft besser als „jeden Tag zur gleichen Uhrzeit ausführen“.
- Beim Leeren eines temporären Verzeichnisses gibt es in
/tmp kurz nach dem Booten vielleicht kaum etwas aufzuräumen, wenn der cron-Zeitpunkt bereits verstrichen ist.
- Die Formulierung „eine Stunde nach dem Start des Computers ausführen und danach stündlich“ passt oft besser zum tatsächlichen Verhalten des Services und zur Logik des Zeitplans.
[Timer]
OnBootSec=1h
OnUnitActiveSec=1h
OnBootSec=1h bedeutet: einmal eine Stunde nach dem Start der Maschine ausführen.
OnUnitActiveSec=1h bedeutet: eine Stunde nach der Ausführung von Unit= erneut ausführen, wodurch der Timer implizit dauerhaft wiederholt wird.
- Solche periodischen Zeitspannen passen häufiger zu „ab und zu mal ausführen“ als Ausdrücke wie „jede Stunde zu dieser Minute“.
- Beim Beispiel eines Slack-Bots, der die Advent of Code-API pollt, hält der
cron-Ausdruck */15 zwar die Richtlinie „alle 15 Minuten“ der API ein, aber wenn alle auf dieselbe Weise pollen, kann sich der Traffic ballen.
- Wenn man nach einer Codeänderung den Timer startet und ihn dann jeweils 15 Minuten später ausführen lässt, erfüllt man das gewünschte Verhalten und reduziert womöglich das thundering herd-Problem.
Timer-Status auf einen Blick
systemctl list-timers ist ein High-Level-Befehl, der die Timer-Situation auf einem System zusammenfasst.
systemctl list-timers
NEXT LEFT LAST PASSED UNIT ACTIVATES
Mon 2026-04-20 15:15:00 MDT 1min 40s Mon 2026-04-20 15:00:05 MDT 13min ago zfs-snapshot-frequent.timer zfs-snapshot-frequent.service
Mon 2026-04-20 15:32:16 MDT 18min Mon 2026-04-20 14:22:15 MDT 51min ago fwupd-refresh.timer fwupd-refresh.service
Mon 2026-04-20 16:00:00 MDT 46min Mon 2026-04-20 15:00:05 MDT 13min ago logrotate.timer logrotate.service
Mon 2026-04-20 16:00:00 MDT 46min Mon 2026-04-20 15:00:05 MDT 13min ago zfs-snapshot-hourly.timer zfs-snapshot-hourly.service
Tue 2026-04-21 00:00:00 MDT 8h Mon 2026-04-20 09:43:22 MDT 5h 29min ago zfs-snapshot-daily.timer zfs-snapshot-daily.service
Tue 2026-04-21 07:31:28 MDT 16h Sun 2026-04-19 20:15:47 MDT 7h ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service
Mon 2026-04-27 00:00:00 MDT 6 days Mon 2026-04-20 09:43:22 MDT 5h 29min ago zfs-snapshot-weekly.timer zfs-snapshot-weekly.service
Mon 2026-04-27 01:09:27 MDT 6 days Mon 2026-04-20 09:43:22 MDT 5h 29min ago fstrim.timer fstrim.service
Mon 2026-04-27 04:28:38 MDT 6 days Mon 2026-04-20 09:43:22 MDT 5h 29min ago zpool-trim.timer zpool-trim.service
Fri 2026-05-01 00:00:00 MDT 1 week 3 days Wed 2026-04-01 10:07:51 MDT 1 week 1 day ago zfs-snapshot-monthly.timer zfs-snapshot-monthly.service
Fri 2026-05-01 03:17:17 MDT 1 week 3 days Wed 2026-04-01 10:07:51 MDT 1 week 1 day ago zfs-scrub.timer zfs-scrub.service
11 timers listed.
Pass --all to see loaded but inactive timers, too.
- Mit einem einzigen Befehl erhält man einen Gesamtüberblick über alle Elemente, die nach Timer-Zeitplänen laufen.
list-timers gehört zu einer häufig genutzten Familie von systemd-Unterbefehlen.
list-units ist ebenfalls nützlich.
list-paths ist ein neuerer Unterbefehl, der systemctl hinzugefügt wurde.
Aus dem Ruhezustand aufwecken und ausführen
WakeSystem= kann dafür sorgen, dass ein abgelaufener Timer das System aus dem Ruhezustand aufweckt.
WakeSystem=
Takes a boolean argument. If true, an elapsing timer will
cause the system to resume from suspend, should it be
suspended and if the system supports this.
...
- Das ist nützlich, wenn ein wichtiges Skript laufen soll, ohne dass jemand physisch den Laptopdeckel öffnen muss.
- Auf Distributionen wie Arch oder NixOS, die das Herunterladen von Paket-Updates vor der eigentlichen Nutzung unterstützen, kann man spät nachts Update-Pakete vorab holen und sie morgens an der Tastatur installieren.
- Laut Handbuch muss man das erneute Versetzen in den Ruhezustand manuell veranlassen, wenn das System nach Abschluss der
.service wieder schlafen soll.
Ausführungszeiten streuen und thundering herd entschärfen
- Das thundering herd-Problem ist ein Systemproblem, das auftritt, wenn viele Prozesse gleichzeitig aufwachen.
- Wenn weltweit alle Debian-Systeme hart auf
00:00:00 für apt update eingestellt wären, wäre Mitternacht für alle eine schlechte Traffic-Spitzenzeit.
FixedRandomDelay= und RandomizedOffsetSec= helfen dabei, Ausführungszeiten zu verteilen.
FixedRandomDelay=
Takes a boolean argument. When enabled, the randomized delay
specified by RandomizedDelaySec= is chosen deterministically,
and remains stable between all firings of the same timer,
even if the manager is restarted. ...
RandomizedOffsetSec=
Offsets the timer by a stable, randomly-selected, and evenly
distributed amount of time between 0 and the specified time
value. ...
- Solche Einstellungen können auf realen Systemen verwendet werden, die nach Software-Updates suchen.
- Eine gleichmäßige Verteilung der Ausführung hilft, das thundering herd-Problem zu reduzieren, das Verhalten konsistent zu halten und Störungen wie Daemon-Neustarts während der Koordination verteilter Dienste zu vermeiden.
- Insgesamt sind die Timing-Optionen sehr gut konfigurierbar und bieten feingranulare Kontrolle.
Verpasste Ausführungen sofort nachholen
Persistent= eignet sich besonders für geplante Skripte, die wegen eines schlafenden Laptops nicht verpasst werden sollten, für die aber WakeSystem= nicht nötig ist.
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. ...
- Wenn ein für Konfigurationsmanagement geplantes Check-in-System Ausfallzeit hatte, kann schon
Persistent= in der .timer genügen, damit es direkt nach dem Wieder-Online-Gehen in den richtigen Zustand konvergiert.
- Ohne
Persistent= muss man womöglich bis zum nächsten regulären Ausführungszeitpunkt des Timers warten, und das kann lange dauern.
- Weitere Aufgaben, bei denen man bei erkannter verpasster Aktivierung nicht warten sollte, sind System-Updates oder die Prüfung von Batch-Jobs.
Worauf man beim Schreiben von Timern achten sollte
- Timer im Kontext des Benutzer-Managers, die mit
systemctl --user verwaltet werden, sind ebenfalls sinnvoll, aber man sollte auf das Ziel im [Install]-Abschnitt achten.
- Je nach Distribution kann für Benutzer-Timer
default.target das passende Ziel sein.
- Wie bei
cron gilt weiterhin der allgemeine Hinweis, dass eine korrekte Systemzeit wichtig ist.
- systemd-Nutzer können den Synchronisationsstatus mit
timedatectl timesync-status prüfen.
- Viele Editoren unterstützen das Format von systemd-Unit-Dateien direkt, was bei größeren Unit-Dateien hilfreich ist.
- In Emacs kann man das Paket emacs systemd verwenden.
2 Kommentare
Hacker-News-Kommentare
Ich habe systemd-Timer nicht oft genug verwendet, um dem entschieden zu widersprechen, aber die Aussage, dass $PATH bei cron unklar ist, verstehe ich nicht so recht.
Man kann
PATHdirekt in der crontab setzen; ich sehe nicht, warum das unvorhersehbarer sein soll als Einstellungen in/etc/bashrc,~/.bashrc,~/.profile,~/.bash_profileoder/etc/systemd/….Ich nutze Linux seit 1994, habe mir aber die cron-Syntax nicht auswendig gemerkt. In den Kommentaren der crontab steht jedoch schon
m h dom mon dow command, also muss man nur passend zu den Bezeichnungen die Zahlen eintragen.Die übrigen Beschwerden kann ich nachvollziehen, und wenn ich das nächste Mal einen cron-Job brauche, werde ich wohl einmal systemd-Timer ausprobieren.
Es gibt Kommas, Schrägstriche, Sternchen und Kombinationen davon, und wenn man Randomisierung braucht, geht das mit cron selbst normalerweise nicht, sodass man sie in den Befehl einbauen muss. Eine nichttriviale cron-Spezifikation zu schreiben ist nicht einfach.
Wenn jemand etwas wie
5,3/4 4-8,11 1 4,5,6,9-11 */2einträgt, beginnt der Spaß des Reverse Engineerings, was eigentlich gemeint war — und meist ist es nicht das, was tatsächlich geschrieben wurde.Mit Erweiterungen, die nur in manchen cron-Umgebungen unterstützt werden, wird es noch komplizierter.
systemd-Timer waren deutlich angenehmer zu verwalten. Die Kontrolle darüber, ob lang laufende Jobs mehrfach parallel laufen dürfen, oder die Möglichkeit, Jobs innerhalb eines Start-Ende-Fensters statt zu einer festen Uhrzeit auszuführen, sind große Verbesserungen.
Früher ist einmal ein Backup-Job in eine Symlink-Schleife geraten und hat meinen VPS lahmgelegt; cron startete trotzdem immer wieder neue Backup-Jobs, obwohl das vorige noch nicht beendet war.
Dass ich wegen des speziellen
PATHvon CRON Befehle und Skripte umschreiben musste, war ebenfalls lästig, auch wenn das bei manchen systemd-Timern ähnlich sein kann. Trotzdem kann man einen Timer manuell starten, ohne die crontab erst auf „in 30 Sekunden“ umzubiegen und dann zu warten.$PATHnicht in die crontab hartcodieren.Wenn ich es nicht hartcodiere, ist der
$PATH, mit dem cron etwas ausführt, anders als der$PATH, den ich beim direkten Testen des Befehls habe.systemctl start foo.servicestartet den Befehl in derselben Umgebung, die auch beim Auslösen des Timers verwendet wird, daher kann ich erkennen, ob er sich gleich verhält.Dagegen laufen cron-Jobs einfach zu der in der crontab angegebenen Zeit. systemd-Timer lösen zwar meist zur angegebenen Zeit aus, können aber wegen Logik-Bugs in systemd nach einer einmaligen Ausführung am 29. Februar nie wieder laufen oder beim „restart“ einer Timer-Unit vielleicht auslösen und vielleicht auch nicht.
Bei systemd ist die tatsächlich ausgeführte Unit dieselbe, egal was sie auslöst, daher gibt es diese Lücke nicht.
Man muss zwar immer noch wissen, was die Standardumgebung ist, aber es ist eine nahezu saubere Umgebung, unbeeinflusst von der Shell. Das sehe ich als Vorteil von systemd.
PATHvöllig unklar ist, aber cron hat durchausPATH-Probleme.In den Standardwerten fehlen oft Dinge, die man erwarten würde, etwa
/usr/local/binoder/usr/sbinfür root, und einige Distributionen wie Arch Linux erwähnen in den Manpages weder den Standardpfad noch empfohlene Einstellungen.Wenn man den Pfad nur für ein bestimmtes Skript erweitern will, muss man mit
envarbeiten, es in einem Wrapper-Skript setzen oder den Pfad vor einem Eintrag ändern und danach wieder zurücksetzen.Man kann in
PATHweder~noch$HOMEverwenden und muss absolute Pfade ausschreiben, was besonders in Benutzer-crontabs lästig ist.Das ist zwar kein schwer zu umgehendes Problem, aber systemd-Timer, die standardmäßig denselben Pfad wie andere Dienste nutzen, bieten aus meiner Sicht die bessere Erfahrung.
Ich bin von cronie auf systemd-Timer umgestiegen, weil sie gegenüber der Systemstartzeit robuster sind.
Meine Backup-Strategie erstellt jeden Tag zu einer festen Zeit einen borg-Archiv-Eintrag, aber bei cronie muss das System zum geplanten Zeitpunkt eingeschaltet sein. systemd-Timer halten diesen Fall aus und führen den Dienst aus, sobald das System verfügbar ist.
Das Repository für die Backup-Automatisierung ist https://github.com/gchamon/borg-automated-backups.
/etc/cron.hourly/0anacronauf und führt dann Jobs aus/etc/cron.{daily,weekly,monthly}aus, auch wenn die früheste Ausführungszeit verpasst wurde. Eine zufällige Verzögerung lässt sich ebenfalls konfigurieren.Wenn man
/etc/anacrontabbearbeitet, kann man eigene Zeitpläne erstellen.Auf Benutzerebene könnte man wohl einen Eintrag wie
@hourly anacron -t /path/to/anacrontab -S /path/to/spooldirin die Benutzer-crontab setzen, ausprobiert habe ich das aber nicht.Viele cron-Implementierungen haben ähnliche Mechanismen.
@reboot, und ich nutze sie in einigen Skripten; sie funktioniert gut.@reboot?Canon-Druckerdüsen können verstopfen, wenn sie eine Weile unbenutzt bleiben, deshalb traue ich ihnen nicht. Also habe ich Claude ein systemd-Skript erstellen lassen, das jede Woche Hundefotos ausdruckt, und dafür gesorgt, dass genug vom CMYK-Spektrum enthalten ist, damit der Drucker ordentlich beschäftigt wird
Es ist jedes Mal eine ziemlich angenehme Überraschung, wenn ich mich montags an den Schreibtisch setze und plötzlich ein Foto aus dem Drucker kommt
Das wäre zumindest eine mögliche Idee für ein Wissenschaftsprojekt der Kinder
Nach seinem Tod stand es ein paar Jahre ausgeschaltet und unbenutzt herum, aber ich brauchte einen Farbausdruck, habe nur den Strom angeschlossen und gedruckt
Nach etwa 1/5 der ersten Seite waren alle Farben wieder da, und danach hat es rund 20 Seiten problemlos gedruckt
Es wirkte eher wie ein Software- als ein Hardwareproblem: Wenn der Drucker länger als eine Woche am Rechner hing und nichts tat, hörte er einfach auf zu drucken
Ich hätte mich durch die Logs wühlen können, aber stattdessen habe ich einen cron-Job eingerichtet, der montags und donnerstags eine Testseite druckte. Oben auf der Testseite stand nur etwas wie
LOL PRINTER WORKSSo verschwenderisch war das gar nicht. Ich hatte viele Mathekurse und brauchte massenhaft Schmierpapier für Rechenwege; zuerst habe ich Fehldrucke oder Testdrucke benutzt und erst danach leere Blätter
Die maximale Auflösung lag zwar nur bei 600dpi, aber die Farben waren sehr gut und gleichmäßig, und dass Toner nicht austrocknet, war für meinen Bruder das wichtigste Kaufkriterium. HP-Tintenstrahldrucker sind ihm mehrfach eingetrocknet
Ich mag systemd-Timer sehr. Ich habe nach und nach alle cron-Jobs, die ich mit Ansible ausgerollt hatte, auf Timer umgestellt, und jetzt muss Ansible sie nur noch kopieren
Besonders gut ist die Integration mit
journalctl, und auf neueren OS ohne syslog wie Debian 13 ist das noch besser. Praktisch ist auch, dass man den Service zum Debuggen manuell starten kannNicht funktionierende cron-Jobs waren immer ein Ärgernis, bei dem man Dinge zusammenkopieren oder zusätzliche Shell-Skripte schreiben musste, ganz zu schweigen vom schwarzen Loch, in dem die Standardausgabe von cron-Jobs verschwindet
Man kann systemd-Services wie bisher überwachen und Benachrichtigungen bei Fehlern bekommen. Ich finde es auch gut, dass Open-Source-Projekte Timer zunehmend als Deployment-Methode empfehlen
NixOS setzt standardmäßig auf systemd und nutzt es als erstklassigen Bestandteil der Verwaltung. Besonders gut ist das, wenn man von macOS mit launchd kommt
Schön ist auch, dass man beim Verteilen von Tools für NixOS systemd natürlich nutzen kann, statt es nachträglich als Behelf dranzuflicken
Wenn man allerdings ein Tool mit viel Lifecycle-Management für alle Linux-Nutzer ausliefern will, frage ich mich, was man tun soll, weil systemd eben nicht überall vorhanden ist
Ich lasse den monatlichen Scrub meines btrfs-Pools über einen systemd-Timer laufen. Es ist ziemlich nützlich, dass man festlegen kann, ob der nächste geplante Lauf übersprungen wird, wenn der Benutzer selbst einen Scrub startet, oder ob sich Jobs aufstauen bzw. zu einem einzelnen Lauf zusammengefasst werden, wenn ein monatlicher Job geplant ist, das Gerät aber 6 Monate ausgeschaltet war
systemd.services.sync-recyclarr = { serviceConfig.Type = "oneshot"; path = [ pkgs.podman ]; script = '' podman exec -it recyclarr recyclarr sync radarr podman exec -it recyclarr recyclarr sync sonarr ''; };systemd.timers.sync-recyclarr = { timerConfig = { OnCalendar = "daily"; Persistent = true; Unit = "sync-recyclarr.service"; }; partOf = [ "sync-recyclarr.service" ]; requires = [ "podman-recyclarr.service" ]; wantedBy = [ "timers.target" ]; };flake.nix-Datei definierstIch nutze auch NixOS, halte meine Konfigurationen aber alle im ursprünglichen Format und lasse Nix nur symbolische Links darauf setzen. So kann ich die Konfiguration auch auf Nicht-NixOS-Systemen leicht wiederverwenden
Das Problem ist, dass NixOS anscheinend systemd-Timer und -Services aus dem Ordner
~/.config/systems/usernicht aufgreift und startet, und Dinge wieWantedBy=default.targetscheinen auch keine Wirkung zu habenDeshalb stimme ich erst dann zu, dass systemd-Timer großartig sind, nachdem ich nach einem Neustart alle Services manuell neu gestartet habe
Timer funktionieren überraschend flexibel nicht nur mit Service-Units gleichen Namens, sondern auch mit beliebigen anderen Units
Auf meinem Server gibt es einen Timer, der jeden Morgen mit zufälliger Startzeit und Benachrichtigung
backup.targetstartet, das den gesamten Backup-Zyklus mitrestic backup,restic pruneundrestic forgetausführtDie eigentlichen
restic-*-Units sind Podman-Quadlets, daher funktioniert die Konfiguration unabhängig vom Serverinhalt, solange nur Podman und Systemd vorhanden sindAllerdings gehören Timer zu den sperrigsten systemd-Unit-Typen für den täglichen Gebrauch. Ich verstehe, warum sie in zwei Dateien aufgeteilt sind und warum sich die Syntax für start und enable unterscheidet, aber manchmal möchte ich einfach nur eine Datei erstellen, ein Skript ausführen und fertig
Im Zeitalter der LLMs ist das vielleicht kein großes Problem mehr, aber es fühlt sich jedes Mal ein bisschen umständlich an
Ich mochte bestimmte Aspekte von systemd nie besonders, stimme diesem Eindruck aber größtenteils zu.
Für geplante Aufgaben auf „System“-Ebene nutze ich inzwischen fast gar kein cron mehr und bevorzuge systemd-Timer. Für Scheduling im Rahmen einer bestimmten Anwendung kann man auch etwas wie Quartz einsetzen.
Der Grund ist etwas vage und schwer zu erklären, aber der systemd-Ansatz passt sauberer zu meinem mentalen Modell davon, „wie so etwas funktionieren sollte“. Früher hatte ich auch öfter Fälle, in denen die
PATH-Umgebung bei cron-Skripten unklar war und das Verhalten schwer vorhersehbar wurde, aber das ist nicht alles.Ich würde nicht behaupten, dass systemd-Timer universell und objektiv besser sind als cron, aber mich haben sie zumindest überzeugt.
Das war ein sehr guter Einstieg in systemd-Timer und überzeugend genug, dass ich sie jetzt endlich ausprobieren werde.
list-timersgefällt mir auch. Bei cron war es nie einfach, sich auf einen Blick einen Überblick über alle Cronjobs auf einer Maschine zu verschaffen. Man musste die Crontabs aller Benutzer,/etc/cron.d/sowie die daily/hourly/monthly-Verzeichnisse prüfen.Ich habe tatsächlich einen Anwendungsfall, der etwa 5 Minuten nach dem Booten einmal laufen und danach etwa alle 12 Stunden ausgeführt werden soll, und es ist schön, dass systemd-Timer das abdecken.
systemd-analyzeundsystemctl list-timerszu lernen.systemd wirkt am Anfang komplex, aber wenn man es erst einmal benutzt, möchte man nichts anderes mehr verwenden. Es ist bequem, alles mit
systemctlzu verwalten.Zum Beispiel verstehe ich nicht, warum Unit-Definitionen zwingend echte Dateien auf der Festplatte sein müssen. Wenn der Daemon neu lädt, liest er nicht nur geänderte Dateien neu ein, sondern alle. Ich frage mich, warum es keine API gibt, mit der man Units programmatisch hinzufügen kann. Es gibt zwar etwas Ähnliches, aber das hat viele Einschränkungen und ist nicht flexibel.
Dass man in einer Datei nicht mehrere Units deklarieren kann, finde ich ebenfalls fragwürdig. Die Entscheidung für ein dateisystemzentriertes Design ohne andere Abstraktionsebenen wirkt nicht besonders klug. Mit der Unix-Philosophie hat das auch nicht gerade viel zu tun.
Auch beim Format der Unit-Definitionen denke ich, dass man etwas Vernünftigeres gewählt hätte, wenn es TOML damals schon gegeben hätte.
Klar, wahrscheinlich bin ich einfach alt. Natürlich ist nur
systemd-*der einzig richtige Weg, und alle, die das anders sehen, sind bloß Besserwisser.Ich nutze Linux seit über 20 Jahren und systemd seit über 10 Jahren.
Trotzdem gibt es immer noch Neues zu lernen, und ich betrachte das tatsächlich wieder als ein weiteres nützliches Werkzeug.
Lobste.rs-Meinungen
systemd ist zwar nicht perfekt, aber viele Designentscheidungen wirken so, als würden sie auf Erkenntnissen aus traditionelleren früheren Ansätzen beruhen
Ich habe mir neulich noch einmal die Episode von CRE aus dem Jahr 2015 angehört, in der Lennart Poettering den Hintergrund erklärt, und kann sie immer noch empfehlen
Ich gehöre eher zur Fraktion, die systemd durch und durch nicht mag, aber systemd.timers halte ich für eines der „weniger schlechten“ Konzepte dieses Produkts
Deshalb war ich etwas überrascht, dass der Autor es auf eine Weise verteidigt hat, die Leute mit berechtigten Beschwerden herabsetzt
Trotzdem ist die Nutzung zusammen mit dem
at-Befehl gut. Für Befehle, die einmal zu einem bestimmten Zeitpunkt ausgeführt werden sollen, nutze ichat, und für alles andere systemd-Timer mit einfachen Unit-DateienDie Verbesserung, die ich am liebsten sehen würde, wäre, erkennen zu können, welcher Benutzer einen Timer ausführt. Ich bin zwar einer der wenigen Leute, die 2026 noch eine Shellbox betreiben, aber es wäre nützlich zu wissen, welcher Benutzer einen Timer eingerichtet hat, der jede Sekunde auf die Festplatte hämmert
Soweit ich weiß, kann es mit
loginctl enable-lingerauch ohne aktive Benutzersitzung laufen. Natürlich gibt es sicher Anwendungsfälle, für die das nicht ausreicht, aber ich kenne die konkrete Situation nichtBei systemd-Timern wäre es besonders auf der Seite der Benutzerverwaltung schön, wenn die Einstiegshürde niedriger wäre
Wenn man sieht, wie viel Konfiguration nötig ist, ist
crontab -ewirklich nur schwer zu schlagenIch habe lange darüber nachgedacht, wie man Logs von cron-Skripten systematisch sammeln kann, und dann gemerkt, dass man einfach systemd-Timer verwenden kann
Das Logging-Problem ist damit gelöst. Jetzt habe ich keinen Grund mehr, wieder cron zu verwenden, und wünschte, ich hätte das früher gewusst
loggerweiterleiten oder mit>>an eine Logdatei anhängen oder die Standardeinstellung beibehalten und E-Mails empfangen?Nennt es ruhig altmodisch, aber auf Servern richte ich mir immer noch E-Mail ein, die mich erreicht
Wenn man das automatisiert, ist es auf jedem neuen Host kostenlos mit dabei, und auch im Alltag ziemlich praktisch
Zum Beispiel öffne ich einen Multiplexer, führe
long_running_process | mail root@localhost -s "done $?"aus und vergesse es dann einfachGuter Artikel, und ich hatte selbst einen Entwurf für einen ähnlichen Artikel, auf den ich kürzlich wieder zurückgreifen musste
Wenn man wie ich in den systemd-Kaninchenbau hinabsteigt, empfehle ich, die Unit-Dateien und Timer im zugehörigen Projektordner nach
/etc/systemd/system/symbolisch zu verlinkenEine meiner Beschwerden über systemd ist, dass es nicht zwischen von der Distribution installierten Units und selbst geschriebenen Units unterscheidet, aber mit symbolischen Links kann man diese Trennung selbst aufrechterhalten
System-/Paket-/Distributions-Units liegen unter
/usr/lib/systemd/system, und lokale Overrides oder lokale Units unter/etc/systemd/system