Uhren

Was bevorzugt ihr: cron oder systemd.timer?

Der Daemon cron dient bereits seit den späten 70er-Jahren zur zeitbasierten Ausführung von Prozessen auf lokalen Rechnern oder entfernten Servern. Der Name cron steht angeblich für command run on notice. Man kann aber auch eine Verwandtschaft zum griechischen Gott Chronos oder dem Titanen Kronos als der Personifizierung der Zeit vermuten. Ken Thompson als ursprünglicher Autor sagt, cron sei ein Schreibfehler seinerseits, es sollte eigentlich chron heißen.

CronJobs

CronJobs werden in einer systemweiten oder User-spezifischen Tabelle gespeichert. Beim Plasma-Desktop lassen sich CronJobs in den Systemeinstellungen unter Starten und Beenden > Aufgabenplaner verwalten. Unter GNOME erledigt das die GUI Geplante Aufgaben, die als Paket gnome-schedule heißt.

systemd.timer

Wie nicht anders zu erwarten beherrscht auch systemd die Fähigkeit, über Timer zu vorgegebenen Zeiten automatisch Aufgaben auszuführen. Das dahinterstehende Modul heißt systemd.timer und wird über Timer-Units gesteuert. Da stellt sich mancher jetzt sicher die Frage, warum es neben dem bewährten cron einen systemd-Dienst gibt, der die gleiche Aufgabe übernimmt.

Dem wollen wir in diesem Artikel auf den Grund gehen. Dazu schauen wir zunächst, wie die beiden Varianten aufgesetzt werden und verwenden hierzu die Aufgabe, Flatpaks automatisch vom System aktualisieren zu lassen. Bei cron benötigen wir nur eine Zeile, aber die ist ein wenig fehleranfällig, wenn man das nicht täglich macht.

cron

0 6  *  *  * /usr/bin/flatpak update -y

Diese Zeile führt jeden Morgen um 06:00 ein Update der installierten Flatpaks aus. Im Fall von Flatpak benötigt man unter Umständen zwei CronJobs, da Flatpaks im User- und im System-Kontext installiert werden können. Die Definition des Ausführungszeitpunkts wird über die fünf Sterne vorgenommen und richtet sich nach folgendem Schema:

Quelle: Wikipedia

Crontab

Zum Erstellen und Editieren dient der Befehl crontab -e, der eine Sitzung im bevorzugten Editor öffnet. Nicht funktionierende Einträge werden beim Speichern angemahnt. Ich finde das Schema zur Festlegung der Ausführungszeit wenig intuitiv und fehleranfällig.

systemd.timer

Unter systemd werden für die Aufgabe zwei Dateien erstellt, die mit .service und .timer enden. Erstere definiert, was zu tun ist, die Zweite legt fest, wann dies passieren soll. Die beiden Dateien sehen für unser Beispiel folgendermaßen aus:

sudo nano /etc/systemd/user/flatpak-updates.service

[Unit]
Description=Update user Flatpaks
[Service]
Type=oneshot
ExecStart=/usr/bin/flatpak --user update -y

Der System-Typ oneshot ist ähnlich wie beim Typ simple, allerdings betrachtet systemd die Einheit als beendet, nachdem der Hauptprozess beendet wurde. Weitere Informationen über Service-Typen kann man bei Red Hat nachlesen.

Timer:

[Unit]
Description=Update user Flatpaks daily at 06:00
[Timer]
OnCalendar=*-*-* 06:00:00
Persistent=true
[Install]
WantedBy=timers.target 

WantedBy

Die Timer-Unit stellt sicher, dass die Service-Unit zum gewünschten Zeitpunkt ausgeführt wird. Der Parameter WantedBy=timers.target sorgt in diesem Fall dafür, dass systemd den Timer beim Systemstart zusammen mit allen anderen Timern aktiviert.

Generell wird die Eigenschaft WantedBy verwendet, um die Abhängigkeiten zwischen verschiedenen Units zu kontrollieren. Durch die Angabe der Zieleinheiten, mit denen ein bestimmter Dienst gestartet werden soll, kann systemd sicherstellen, dass die erforderlichen Dienste in der richtigen Reihenfolge gestartet werden, um die Abhängigkeiten zwischen ihnen zu erfüllen.

Im User-Kontext speichern

Die beiden erstellten Dateien werden, mit beliebigen Namen, aber den korrekten Endungen versehen, in diesem Fall unter /etc/systemd/user abgelegt. Neben der Direktive OnCalendar gibt es noch viele weitere Direktiven zur Definition des Ausführungszeitpunkts. Der Parameter Persistent=true sorgt dafür, dass Timer nachgeholt werden, falls der Rechner zum Ausführungszeitpunkt ausgeschaltet war.

Eine weitere absolute Zeitangabe bewirkt etwa, dass ein Timer an jedem Montag des Jahres 2023 um sechs Uhr morgens ausgeführt wird:

OnCalendar=Mon 2023-*-* 06:00

In den Beispielen haben wir absolute Zeitangaben vorgegeben. aber es können auch verschiedene Aufgaben kombiniert werden: Soll etwa ein Job 10 Minuten nach einem Neustart des Rechners und dann einmal täglich zur gleichen Zeit ausgeführt werden, nimmt man statt OnCalendar= die Direktiven:

OnBootSec=10m
OnUnitActiveSec=1d

Was in dem Zusammenhang möglich ist, vermittelt die Manpage von systemd.time. Eine gute Übersicht, wie systemd Kalenderzeit, Zeitstempel und Zeitspannen verwendet, vermittelt ein Artikel auf opensource.com. Auch das Arch-Wiki vermittelt, wie gewohnt, einen guten Überblick.

Sind die beiden Dateien erstellt und gespeichert, muss der Timer noch aktiviert werden:

sudo systemctl --user enable --now flatpak-update.timer
sudo systemctl daemon-reload

Um abschließend zu sehen, wann der Timer das nächste Mal startet, dient in unserem Beispiel der Befehl

systemd-analyze calendar 06:00

Alternativ zeigt der Befehl systemctl list-timers alle aktiven Timer und deren nächste Ausführung.

Bewertung

Ein Vergleich systemdtimer vs. cron ist ein wenig wie systemd vs. SysVinit. Auf den ersten Blick scheint das Aufsetzen eines systemd.timers allerdings aufwändiger als das von cron zu sein. Was spricht also für den Einsatz von systemd anstelle von CronJobs?

Für mich spricht einiges für systemd:

  • Die Definition von Zeitpunkten und Zeiträumen ist verständlicher und wesentlich flexibler
  • Es fasst cron und anacron zusammen
  • Es weckt per weckt WakeSystem=true Geräte aus dem Suspend-Modus
  • Das Journal gibt mit einem Befehl Auskunft über die Ausführung von Timer-Units
  • Testing und Debugging ist wesentlich einfacher
  • Mit der Option dependencies können wie bei anderen systemd-Diensten Abhängigkeiten zur Aktivierungszeit definiert werden.
  • Einfach über systemctl enable/disable zu (de)aktivieren
  • systemd.timer können mit verschiedenen Zeitzonen umgehen
  • systemd verschickt auf Wunsch per OnFailure-Direktive eine E-Mail beim Scheitern eines Timers

Gegen systemd.timer sprechen für mich zwei Dinge:

  • MAILTO bei cron ist einfacher als OnFailure bei systemd
  • systemd.timer funktionieren nur unter Linux und nur bei Distributionen, die systemd verwenden.

Was verwendet ihr?

Letztlich sind systemd.timer für mich aber wesentlich flexibler und besser ins Gesamtsystem integriert. Wie haltet ihr es mit der zeitgesteuerten Ausführung von Befehlen, Scripten und anderen Aufgaben?

Bildquelle: Photo by Alex Guillaume on Unsplash

Teilt den Beitrag, falls ihr mögt

Vielleicht gefällt Dir auch

21 Kommentare
Newest
Oldest Most Voted
Inline Feedbacks
View all comments