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

22 Kommentare

  1. Ich benutze cron. Wäre hier ein systemd in Nutzung, würde ich sehr warhscheinlich immer noch cron nutzen am Anfang. Prinzipiell ist es mir egal ob ein Linux System systemd oder open-rc benutzt oder Etwas anderes. Ich muss mit allen Paketen irgendwie klar kommen.

    Hier im Thread sieht man ganz gut dass viele User trotzdem immer noch cron nutzen, weil sie alle wie ich auch im Grunde faul sind und auf das was sie kennen setzten. Faulheit siegt.

    Wenn beim Kunden ein SystemD in Benutztung ist, gut, wenn was anderes da ist auch gut. Wenn ein Kunde nur ein kommerzielles UNIX zur Verfügung stellt, ebenfalls OK ich bin froh dass ich Zugriff darauf habe und es nutzen darf.

    0
  2. Persistent=true ist im Desktop-Bereich finde ich einer der größten Vorteile von Timern gegenüber cronjobs.

    In der Regel verwende ich Cronjobs tatsächlich primär für ‘quick and dirty’ Sachen, die eh mehrmals am Tag laufen sollen (z.b. Verbindungschecks o.ä.).

    Da man viele Dinge mit nem .service sehr schön abbilden kann, wenn man mal ein bisschen durchgestiegen ist passt es für permanente bzw aufwändigere Sachen dann aber finde ich auch besser bei der Gelegenheit mit Timern zu arbeiten, auch wenn ich beim erstellen auf jeden Fall deutlich häufiger die Dokumentation bemühen muss als bei cron 😀

    1
  3. Ich bin immer noch für das KISS-Prinzip. Auch wenn es nicht hip ist.
    Für mich ähnelt systemd einem Krebsgeschwür. Sorry.
    Es breitet sich immer weiter aus übernimmt Dinge für die es nicht gestartet wurde.
    Es soll für das Starten von Services zuständig sein. Und für sonst nichts!
    Somit benutzte ich immer noch am liebsten cron.
    Einmal weil es dem KISS enspricht, weil es simple ist, schnell einzurichten und nur eine Datei. Und weil man Mails bekommt.
    Systemd.timer sind viel zu aufgeblasen, zu aufwenig, irgendwie so hingebastelt und ich kann mir die ganzen Dinger nicht merken was und wie man timer angibt.
    Und ehrlich gesagt will ich es auch aus dem oben angegeben Grund nicht.

    2
    1. Entweder bin ich zu blöd oder etwas stimmt nicht bei meinen Systemen. Aber @reboot, @daily, @weekly, usw. funktionieren nicht zumindest nicht zuverlässig. Habe es aufgegeben und nutze anacron und bei neuen Sachen dann zunehmend Systeme. Insbesondere beim mounten von nezzlaufwerken und backups.

      0
  4. Es kommt drauf an:

    Für mal eben schnell nach der Einrichtung von irgendwas ein Cron, oder auch in der Testumgebung. Produktiv mittlerweile systemd-timer

    Cron geht halt schneller, das ist schon ins Blut übergegangen. Bei den Timern muss ich immer Suchen weil sonst die Hälfte an notwendigen Infos fehlt

    1
  5. Systemd mag Vorteile haben, ok. Aber ich bin ein EDV-Urgestein (seit 46 Jahren) – wie cron. Mit Kernighan und Ritchie habe ich damals C gelernt (die Bücher stehen hier immer noch) und ich habe diesen sympathischen Tippfehler schon in Unix 7 geliebt. Ich denke, ich bleibe dabei. Mal sehen, wieviele Jahrzehnte cron noch überleben wird! 🙂

    1

Kommentar hinterlassen