ADMIN

2021

09

2021-09-01T12:00:00

Clientmanagement und Support

PRAXIS

060

Open-Source-Tipp

Systemmanagement

Prozesse mit systemd-Timer steuern

Zur rechten Zeit

von Thorsten Scherf

Veröffentlicht in Ausgabe 09/2021 - PRAXIS

Um beliebige Aufgaben automatisch auszuführen, kommen auf Linux-Systemen üblicherweise cron und anacron zum Einsatz. Allerdings bietet auch der System- und Service-Manager systemd eine ähnliche Funktion an. Diese kommt sogar mit zusätzlichen Features daher und gilt somit als echte Alternative zu den beiden Unix-Urgesteinen. Der Open-Source-Tipp zeigt, wie Sie solche systemd-Timer anlegen und verwalten können.

Die beiden Tools cron und anacron kommen immer dann zum Einsatz, wenn Programme oder Skripte automatisch zu bestimmten Zeitpunkten oder in Intervallen starten sollen. Mit cron können Sie dies bis auf die Minute genau festlegen, anacron hingegen achtet darauf, dass ein Job unmittelbar gestartet wird, wenn ein bestimmtes Intervall bereits überschritten wurde.
Unix-Urgesteine cron und anacron
Ein konkretes Beispiel könnte so aussehen, dass Sie mit cron einen Job definieren, der jeden Montag Morgen um 06:30 abläuft. Wenn der Rechner, auf dem der Job laufen soll, allerdings zu diesem Zeitpunkt offline ist, dann startet der Job frühestens am Montag in der Woche darauf um 06:30 Uhr. Um dieses Problem zu lösen, definieren Sie mit anacron Intervalle, also beispielsweise einen Sieben-Tages-Intervall. Wird der Rechner erst wieder am Dienstag eingeschaltet, weil der Mitarbeiter am Montag krank war, so erkennt das Tool anhand einer Zeitmarke, dass das Intervall bereits um einen Tag überschritten wurde und startet den Job somit umgehend.
systemd-Unit-Typen
Bei systemd ist es so, dass Informationen zur Konfiguration der Services in unterschiedlichen Unit-Typen hinterlegt sind. Von Interesse in diesem Zusammenhang sind die Service- und Timer-Units. In den Service-Units definieren Sie den eigentlichen Job, der zu einem bestimmten Zeitpunkt laufen soll – also beispielsweise ein Programm oder Skript. In der dazugehörigen Timer-Unit definieren Sie dann den Zeitpunkt, zu dem dieser Job genau ablaufen soll. Hierfür stehen Ihnen eine Vielzahl von Parametern zur Verfügung, mit denen Sie den genauen Startzeitpunkt festlegen. So können Sie beispielsweise auch Event-basierte Zeitangaben vornehmen, also beispielsweise eine Zeit, die relativ zum letzten Bootvorgang oder dem Starten der eigentlichen systemd Service-Unit vergangen ist. Eine komplette Übersicht finden Sie in der Hilfeseite zu systemd.timer. Das Bild zeigt die Default-Timer auf einem Fedora-System an.
Die beiden Tools cron und anacron kommen immer dann zum Einsatz, wenn Programme oder Skripte automatisch zu bestimmten Zeitpunkten oder in Intervallen starten sollen. Mit cron können Sie dies bis auf die Minute genau festlegen, anacron hingegen achtet darauf, dass ein Job unmittelbar gestartet wird, wenn ein bestimmtes Intervall bereits überschritten wurde.
Unix-Urgesteine cron und anacron
Ein konkretes Beispiel könnte so aussehen, dass Sie mit cron einen Job definieren, der jeden Montag Morgen um 06:30 abläuft. Wenn der Rechner, auf dem der Job laufen soll, allerdings zu diesem Zeitpunkt offline ist, dann startet der Job frühestens am Montag in der Woche darauf um 06:30 Uhr. Um dieses Problem zu lösen, definieren Sie mit anacron Intervalle, also beispielsweise einen Sieben-Tages-Intervall. Wird der Rechner erst wieder am Dienstag eingeschaltet, weil der Mitarbeiter am Montag krank war, so erkennt das Tool anhand einer Zeitmarke, dass das Intervall bereits um einen Tag überschritten wurde und startet den Job somit umgehend.
systemd-Unit-Typen
Bei systemd ist es so, dass Informationen zur Konfiguration der Services in unterschiedlichen Unit-Typen hinterlegt sind. Von Interesse in diesem Zusammenhang sind die Service- und Timer-Units. In den Service-Units definieren Sie den eigentlichen Job, der zu einem bestimmten Zeitpunkt laufen soll – also beispielsweise ein Programm oder Skript. In der dazugehörigen Timer-Unit definieren Sie dann den Zeitpunkt, zu dem dieser Job genau ablaufen soll. Hierfür stehen Ihnen eine Vielzahl von Parametern zur Verfügung, mit denen Sie den genauen Startzeitpunkt festlegen. So können Sie beispielsweise auch Event-basierte Zeitangaben vornehmen, also beispielsweise eine Zeit, die relativ zum letzten Bootvorgang oder dem Starten der eigentlichen systemd Service-Unit vergangen ist. Eine komplette Übersicht finden Sie in der Hilfeseite zu systemd.timer. Das Bild zeigt die Default-Timer auf einem Fedora-System an.
systemd-Timer löscht temporäre Dateien
Um nun ein besseres Verständnis dafür zu bekommen, wie systemd-Timer funktionieren, schauen Sie sich doch einmal einen der Standard-Timer an. Listing 1 und Listing 2 zeigen die Service- und Timer-Unit-Dateien für "systemd-tmpfiles-clean".
Listing 1: systemd-Service-Unit zum Löschen temporärer Dateien
systemctl cat systemd-tmpfiles-clean.service # /usr/lib/systemd/system/systemd-tmpfiles-clean.service [Unit] Description=Cleanup of Temporary Directories Documentation=man:tmpfiles.d(5) man:systemd-tmpfiles(8) DefaultDependencies=no Conflicts=shutdown.target After=local-fs.target time-set.target Before=shutdown.target [Service] Type=oneshot ExecStart=systemd-tmpfiles –clean SuccessExitStatus=DATAERR IOSchedulingClass=idle
Listing 1: systemd-Timer-Unit zum Löschen temporärer Dateien
systemctl cat systemd-tmpfiles-clean.timer # /usr/lib/systemd/system/systemd-tmpfiles-clean.timer [Unit] Description=Daily Cleanup of Temporary Directories Documentation=man:tmpfiles.d(5) man:systemd-tmpfiles(8) [Timer] OnBootSec=15min OnUnitActiveSec=1d
Wie in Listing 1 zu erkennen ist, wird mithilfe des Parameters "ExecStart" das Programm "systemd-tmpfiles" zusammen mit der Option "clean" aufgerufen. Wie der Name vermuten lässt und wie ein Blick in die Hilfeseite zu diesem Tool bestätigt, kümmert sich das Programm um das Löschen von temporären Dateien. Zu welchem Zeitpunkt dieser Job ablaufen soll, zeigt der Timer aus Listing 2. Hier sind besonders die beiden Parameter "OnBootSec" und "OnUnitActiveSec" interessant. Ersterer gibt an, nach welchem Zeitraum nach einem Systemstart der Job laufen soll, und Letzterer bezieht sich auf den Zeitpunkt, wann der Timer das letzte Mal lief. Ist der Rechner beispielsweise mehrere Tage aus, dann würde der Job also 15 Minuten nach dem erneuten Starten des Rechners ablaufen und nicht eventuell nach einem Tag.
Timer-Formate
Ein weiterer Parameter, der gerne in Timer-Units verwendet wird, lautet "OnCalendar". Hiermit legen Sie einen genauen Zeitpunkt oder ein Intervall fest, zu dem die zum Timer gehörende Service-Unit ausgeführt werden soll. Das korrekte Format für diesen Parameter können Sie der Hilfeseiten zu "systemd.time" entnehmen. Grob zusammengefasst erwartet systemd die Zeitangabe in diesem Format:
Tag-der-Woche Jahr - Monat - Tag - Stunde:Minute:Sekunde
Das folgende Beispiel würde einen Job also nur dann an einem Samstag oder Sonntag ausführen, wenn die Tage auf die ersten drei Kalendertage in einem Monat fallen:
OnCalendar=Sat,Sun *-*-01..03 12:00:00
Auf einem Fedora-System existieren standardmäßig schon einige Default-systemd-Timer.
Auf einem Fedora-System existieren standardmäßig schon einige Default-systemd-Timer.
E-Mails automatisch mit systemd abholen
Das folgende Beispiel zeigt nun, wie Sie einen systemd Timer einrichten können, der alle fünf Minuten läuft und dabei ein beliebiges Shell-Skript startet. Der Autor verwendet ein solches Setup, um mit Hilfe von mbsync regelmäßig neue E-Mails von diversen IMAP-Servern auf den lokalen Rechner zu synchronisieren. Anders als im letzten Beispiel soll nun allerdings kein systemweiter Timer, sondern ein Benutzer-Timer zum Einsatz kommen, sodass auch reguläre Benutzer den Service kontrollieren können, ohne hierfür über root-Rechte verfügen zu müssen. Die Konfiguration hierfür erwartet systemd dann im Heimatverzeichnis eines Benutzers unterhalb von "~/.config/systemd/user/".
Listing 3 zeigt nun eine einfache Service-Unit "email.service", die im Verzeichnis "~/.config/systemd/user/" gespeichert ist. Sie sorgt dafür, dass das Skript "fetch-email.sh" aufgerufen wird. Wann genau dieser Aufruf erfolgt, definieren Sie in der Timer-Unit "email.timer". Diese Datei liegt im gleichen Verzeichnis wie die Service-Unit. Listing 4 zeigt hierfür ein Beispiel. Der Parameter "OnCalendar" enthält hier den Wert "*:0/5". Das Asterisk-Zeichen dient hier wieder als Wildcard-Symbol und die Minuten werden als "0/5" dargestellt, was dafür sorgt, dass der Timer alle fünf Minuten startet.
Listing 3: ~/.config/systemd/user/email.service
[Unit] Description=Lade Emails von allen Accounts Wants=email.timer [Service] Type=oneshot ExecStart=/home/tscherf/bin/fetch-email.sh [Install] WantedBy=multi-user.target
Listing 4: ~/.config/systemd/user/email.timer
[Unit] Description=Timer für Email Abfrage Requires=email.service [Timer] Unit=email.service OnCalendar=*:0/5 [Install] WantedBy=timers.target
Nachdem Sie die beiden Dateien angelegt haben, müssen Sie den neuen Service natürlich noch aktivieren und starten. Dies geschieht wie gewohnt mit Hilfe von systemctl:
systemctl --user enable email
 
systemctl --user start email
Den Status des soeben eingerichteten Dienstes können Sie dann ebenfalls mittels systemctl abfragen:
systemctl --user status email
Abschließend sei noch darauf hingewiesen, dass systemd sämtliche Timer mit einer Genauigkeit von einer Minute startet. Wann genau innerhalb dieses Zeitfensters von einer Minute ein Job abläuft, findet auf zufälliger Basis statt.
Für die meisten Jobs ist dies ausreichend, für manche allerdings nicht. Abhilfe schafft hier der Einsatz des Parameters "AccuracySec". Setzen Sie den Wert auf "1us", wird ein Timer mit einer Genauigkeit von einer Mikrosekunde getriggert.
Fazit
Wer sich von den Schedulern cron und anacron schon immer mehr Flexibilität gewünscht hat, sollte einen Blick auf die systemd-Timer werfen. Hier stehen vielfältige Parameter bereit, die Jobs auch Event-basiert starten. Dabei wirkt das Konzept aufgeräumt, da jeder Timer eine eigene systemd-Service-Unit besitzt.
(dr)