Ein umfassendes Tutorial über alles, was es über Linux Systemd Timer zu wissen gibt, einschließlich verständlicher Beispiele und Erklärungen aller Konfigurationsoptionen
Dieser Blogpost wurde von einer Maschine aus dem Englischen übersetzt. Die Originalversion finden Sie hier: Ultimate Tutorial About Systemd Timers Job Scheduling - The Replacement for Cron Jobs
Bitte kontaktieren Sie uns , wenn etwas nicht klar beschrieben ist, nicht funktioniert, falsch erscheint oder wenn Sie Unterstützung benötigen.
Dieser Blogpost beschreibt, wie man systemd -Timer erstellt, verwaltet und vollständig versteht, die ein Ersatz für klassische Cron-Jobs sind. Systemd-Timer ermöglichen eine viel feinkörnigere Konfiguration davon, wann oder bei welchen Ereignissen Jobs, Skripte, Befehle oder systemd-Services in verschiedenen Linux-Distributionen ausgeführt werden sollen.
Dieser Artikel ist für Linux-Anfänger und fortgeschrittene Benutzer geschrieben. Er zielt darauf ab, leicht verständlich zu sein. Während die Manualpage man systemd.timer manchmal verwirrend sein kann, enthält dieses Tutorial umfangreiche praktische Beispiele und erklärt alle Aspekte und Konfigurationsoptionen von systemd-Timern sehr detailliert.
Systemd-Timer sind ein Scheduling-Mechanismus in Linux-Systemen, die das systemd-Init-System verwenden, wie Debian, Ubuntu, Fedora, RedHat, CentOS, openSUSE, Arch Linux, Oracle Linux, Linux Mint und viele andere. Systemd-Timer bieten eine modernere und flexiblere Alternative zu traditionellen Cron-Jobs und bieten eine viel feinkörnigere Granularität in Bezug auf das Timing sowie Abhängigkeitsmanagement.
Hier sind die Hauptunterschiede zwischen Systemd-Timern und Linux-Cron-Jobs.
Cron ist auf Minutenpräzision beschränkt, während systemd-Timer es Ihnen ermöglichen, die Ausführung mit Sekunden anzugeben beschrieben in Starten eines Systemd-Timers alle paar Sekunden
Systemd-Timer sind in das systemd-Ökosystem integriert: Timer können Abhängigkeiten zu anderen systemd-Timern, Services oder anderen Units haben und können in einer bestimmten Reihenfolge ausgeführt werden
Systemd-Timer können gemäß der tatsächlichen (Wanduhr-)Zeit, der Zeit seit dem Systemstart oder sogar durch Ereignisse wie das Booten des Systems ausgelöst werden
Systemd-Timer können zu einer zufälligen Zeit innerhalb eines gegebenen Zeitintervalls gestartet werden (zum Beispiel zu einer zufälligen Minute zwischen 13 und 14 Uhr)
Wenn die Maschine ausgeschaltet ist (oder anderweitig nicht betriebsbereit), wird systemd automatisch verpasste Timer nachholen, sobald das System wieder online ist (konfigurierbar mit dem Persistent= Parameter )
Logs sind im systemd-Journal zentralisiert. Cron-Jobs pflegten standardmäßig E-Mails an den Linux-Benutzer zu generieren, der den Cronjob besitzt, wenn Ausgabe erzeugt wird
Mehrere Systemd-Timer können für mehrere spezifische Zeitzonen eingerichtet werden, die sich von der Standardzeitzone unterscheiden, die für das System konfiguriert ist
Systemd-Timer können bei sehr ungewöhnlichen Dingen ausgelöst werden, wie dem Administrator einer Maschine, der manuell die Zeit ändert
Das Erstellen eines systemd-Timers erfordert WEITAUS mehr Konfigurationszeilen und Folgebefehle als das Konfigurieren eines Cronjobs. Wenn Sie regelmäßig einen einfachen BASH-Befehl ausführen möchten, reicht das Erstellen eines systemd-Timers nicht aus - systemd-Timer können nur systemd-Services starten, was bedeutet, dass Sie einen systemd-Service konfigurieren müssen, um diesen Befehl auszuführen, der dann vom systemd-Timer ausgelöst wird.
Einige der Konfigurationsoptionen für systemd-Timer sind etwas schwer zu verstehen, wenn man das Manual liest - sie sind viel einfacher aus diesem sehr detaillierten Blogpost zu verstehen ;)
Systemd-Timer werden standardmäßig nicht zur exakt konfigurierten Zeit ausgeführt, sondern innerhalb von +60 Sekunden davon - dies kann jedoch konfiguriert (oder man könnte sagen behoben) werden mit AccuracySec=
Der folgende Abschnitt beschreibt, wie man einen systemd-Timer unter Verwendung des häufigsten Anwendungsfalls für Jobs auf Linux erstellt: periodisches Ausführen eines einfachen Befehls oder BASH-Skripts.
Dieses Beispiel zeigt, wie man einen sehr einfachen und simplen systemd-Timer erstellt. Erstellen Sie zunächst ein einfaches BASH-Skript, das eine Zeichenkette und das aktuelle Datum in /root/timer-test.log schreibt:
cat << 'EOF' > /root/test.sh
#!/bin/bash
echo "I am a test script executing at $(date)" | tee -a /root/test.log
EOF
Machen Sie das Skript ausführbar:
chmod 700 /root/test.sh
Erstellen Sie nun eine systemd-Timer-Unit für das Skript: Diese systemd-Konfigurationsdatei ist das Äquivalent zu dem, was das Ausführungsintervall eines Cronjobs früher war, zum Beispiel */10 * * * *. Der folgende systemd-Timer wird alle 10 Minuten ausgeführt.
cat << EOF > /etc/systemd/system/test.timer
[Unit]
Description=Start the Systemd service test.service every 10 minutes
[Timer]
OnCalendar=*:0/10:*
Persistent=true
[Install]
WantedBy=timers.target
EOF
Der obige systemd-Timer wird den systemd-Service unter Verwendung desselben Namensschemas ausführen - ein Timer namens /etc/systemd/system/test.timer wird den systemd-Service /etc/systemd/system/test.service ausführen. Lassen Sie uns einen systemd-Service unter Verwendung desselben Dateinamens erstellen, aber mit einer .service-Erweiterung:
cat << EOF > /etc/systemd/system/test.service
[Unit]
Description=Execute the BASH script /root/test.sh
[Service]
Type=oneshot
ExecStart=/root/test.sh
EOF
Nach dem Bearbeiten der Datei müssen Sie den folgenden Befehl ausführen, um systemd über die Änderungen an seiner Konfiguration zu informieren. Jedes Mal, wenn Sie eine Datei unterhalb von /etc/systemd/system/ ändern, müssen Sie diesen Befehl ausführen.
systemctl daemon-reload
Wie bei systemd üblich, müssen neu erstellte Units, wie Timer, explizit aktiviert werden. Beachten Sie, dass wenn Sie systemctl start test.timer ausführen, dies den Timer unabhängig davon ausführt, zu welcher Zeit Sie ihn konfiguriert haben!
systemctl enable test.timer
Created symlink /etc/systemd/system/timers.target.wants/test.timer → /etc/systemd/system/test.timer.
Um den Status des neuen Timers zu überprüfen:
systemctl status test.timer
● test.timer - Execute the BASH script /root/test.sh every 10 seconds
Loaded: loaded (/etc/systemd/system/test.timer; enabled; preset: enabled)
Active: active (waiting) since Tue 2024-04-16 16:19:51 CEST; 48s ago
Trigger: Tue 2024-04-16 16:20:50 CEST; 9s left
Triggers: ● test.service
Wenn wir nun in die Datei /root/test.log schauen, zeigt sie, dass das Skript alle 10 Sekunden ausgeführt wird:
cat test.log
I am a test script executing at Tue Apr 16 02:23:50 PM UTC 2024
I am a test script executing at Tue Apr 16 02:24:02 PM UTC 2024
I am a test script executing at Tue Apr 16 02:24:13 PM UTC 2024
Wenn wir ins systemd-Journal schauen (dort sind die Logs), können wir Informationen über die Ausführung des Timers sehen:
journalctl _COMM=systemd
[...]
Apr 16 14:23:50 p1 systemd[1]: Starting test.service - MyScript Service...
Apr 16 14:23:50 p1 systemd[1]: test.service: Deactivated successfully.
Apr 16 14:23:50 p1 systemd[1]: Finished test.service - MyScript Service.
Apr 16 14:24:02 p1 systemd[1]: Starting test.service - MyScript Service...
Apr 16 14:24:02 p1 systemd[1]: test.service: Deactivated successfully.
Apr 16 14:24:02 p1 systemd[1]: Finished test.service - MyScript Service.
Apr 16 14:24:13 p1 systemd[1]: Starting test.service - MyScript Service...
Apr 16 14:24:13 p1 systemd[1]: test.service: Deactivated successfully.
Apr 16 14:24:13 p1 systemd[1]: Finished test.service - MyScript Service.
[...]
Aufmerksame Leser haben möglicherweise bemerkt, dass wir tee im test.sh-Bash-Skript verwenden, was bedeutet, dass das Skript nicht nur die Ausgabe des echo-Befehls in /root/test.log schreibt, sondern auch Ausgabe erzeugt, wenn es ausgeführt wird. Um die Ausgabe anzuzeigen, die von diesem Skript erzeugt wurde, das vom systemd test.service ausgeführt wurde, verwenden Sie diesen Befehl:
journalctl _SYSTEMD_UNIT=test.service
Apr 16 14:46:02 p1 test.sh[749373]: I am a test script executing at Tue Apr 16 14:43:31 UTC 2024
Apr 16 14:46:11 p1 test.sh[749420]: I am a test script executing at Tue Apr 16 14:43:31 UTC 2024
Apr 16 14:46:23 p1 test.sh[749467]: I am a test script executing at Tue Apr 16 14:43:31 UTC 2024
Um einen Systemd-Timer wieder zu deaktivieren, verwenden Sie die folgenden Befehle. Das Deaktivieren eines Systemd-Timers bedeutet, zu verhindern, dass er in Zukunft automatisch startet. Wenn Sie einen Timer deaktivieren, entfernen Sie im Wesentlichen seine Verbindung zu allen Ziel-Units, wodurch er inaktiv wird. Wenn der Timer jedoch gerade läuft, stoppt das Deaktivieren seine aktuelle Ausführung nicht.
systemctl disable test.timer
Removed "/etc/systemd/system/timers.target.wants/test.timer".
Das Stoppen eines systemd-Timers bedeutet, seine aktuelle Ausführung anzuhalten, wenn er läuft. Diese Aktion beendet sofort jede laufende Ausführung des Timers. Das Stoppen eines Timers beeinflusst jedoch nicht seinen Status als aktiviert oder deaktiviert. Selbst wenn Sie einen Timer stoppen, kann er in Zukunft automatisch starten, wenn er aktiviert ist.
systemctl stop test.timer
# dieser Befehl gibt bei erfolgreicher Ausführung keine Ausgabe aus
Schauen wir uns /etc/systemd/system/test.timer und /etc/systemd/system/test.service die wir oben erstellt haben
im Detail an. Um alle verfügbaren Informationen zu systemd-Timern anzuzeigen, siehe man systemd.timer.
Bei systemd-Timern ist OnCalendar wohl die relevanteste Konfigurationsoption. Sie ermöglicht eine sehr feinkörnige Spezifikation, wann ein bestimmter Timer ausgeführt werden soll. Wie bei cron ist die korrekte Angabe zunächst etwas verwirrend. Die Syntax für OnCalendar ist:
OnCalendar=DayOfWeek Year-Month-Day Hour:Minute:Second
Um einen systemd-Timer einmalig zur Epoche (ein üblicher Referenzpunkt in der Zeit in der IT) auszuführen, wäre dies Folgendes. Der folgende Timer würde donnerstags (also jeden Donnerstag) am 1. Januar 1970 um 0 Uhr, 0 Minuten und 0 Sekunden ausgeführt. Beachten Sie, dass diese Aussage exemplarisch ist und natürlich in der realen Welt keinen Sinn macht.
OnCalendar=Thu 1970-1-1 0:0:0
Wie Sie sehen können, ergibt donnerstags (jeden Donnerstag) in der obigen Konstellation keinen Sinn, da wir ein spezifisches Datum angeben. Daher können wir das Thu weglassen, um genau dasselbe Ergebnis zu erhalten. Wenn Sie den DayOfWeek weglassen, bedeutet das entweder jeden Tag der Woche, oder wie im folgenden Beispiel, es bedeutet den Wochentag, der der 1. Januar ist:
OnCalendar=1970-1-1 0:0:0
Systemd-Timer sind normalerweise nicht dazu gedacht, einen systemd-Service einmalig zu starten, sondern periodisch (Sie können sie natürlich so konfigurieren, dass sie nur einmal starten). Um den zugewiesenen systemd-Service eines Timers jeden Donnerstag auszuführen, können wir angeben:
OnCalendar=Thu
Nur Thu anzugeben bedeutet, dass der Timer um 00:00:00 ausgeführt wird. Wenn Sie Werte weglassen, ist das Tool systemd-analyze calendar sehr nützlich, um Ihnen eine normalisierte Form der OnCalendar-Spezifikation zu zeigen, die tatsächlich verwendet wird:
systemd-analyze calendar "Thu"
Original form: Thu
Normalized form: Thu *-*-* 00:00:00
Next elapse: Thu 2024-04-18 00:00:00 UTC
From now: 1 day 6h left
Wie wir es von cron gewohnt sind, wird ein Sternchen (*) verwendet, um alle möglichen Werte anzugeben. Um einen systemd-Timer seinen systemd-Service zu jeder 10. Minute jeder Stunde starten zu lassen (um 0:00:00, 0:10:00, 1:10:00, …, 2:10:00, und so weiter), wäre dies:
systemd-analyze calendar "*:0/10:*"
Original form: *:0/10:*
Normalized form: *-*-* *:00/10:*
Next elapse: Tue 2024-04-16 17:40:00 UTC
From now: 8min left
Um einen Bereich anzugeben, können Sie zwei Punkte verwenden, im folgenden Beispiel wäre das jeden Tag von Montag bis Freitag um 20 Uhr:
systemd-analyze calendar "Mon..Fri 20:0"
Original form: Mon..Fri 20:0
Normalized form: Mon..Fri *-*-* 20:00:00
Next elapse: Tue 2024-04-16 20:00:00 UTC
From now: 2h 26min left
Sie können ein Komma verwenden, um eine Liste anzugeben, in diesem Beispiel montags, mittwochs und freitags um 5 Uhr:
systemd-analyze calendar "Mon,Wed,Fri 5:0"
Original form: Mon,Wed,Fri 5:0
Normalized form: Mon,Wed,Fri *-*-* 05:00:00
Next elapse: Wed 2024-04-17 05:00:00 UTC
From now: 11h left
Wenn Sie Server an mehreren geografischen Standorten betreiben, setzen Sie die Zeitzone Ihres Servers üblicherweise auf UTC. Wenn Sie möchten, dass ein systemd-Timer zu einer bestimmten Zeit in einer anderen Zeitzone läuft, können Sie das auch angeben - in diesem Beispiel samstags und sonntags um 13 Uhr.
systemd-analyze calendar "Sat,Sun 13:0 Europe/Berlin"
Original form: Sat,Sun 13:0 Europe/Berlin
Normalized form: Sat,Sun *-*-* 13:00:00 Europe/Berlin
Next elapse: Sat 2024-04-20 11:00:00 UTC
From now: 3 days left
Um alle verfügbaren Zeitzonen aufzulisten:
timedatectl list-timezones
Africa/Abidjan
Africa/Accra
Africa/Addis_Ababa
[...]
Systemd bietet verschiedene Methoden oder Kategorien zum Auslösen der Ausführung ihrer zugewiesenen Systemd-Services:
Echtzeit-Timer verwenden die tatsächliche echte (Wanduhr-)Zeit, um die Ausführung auszulösen.
Echtzeit-Timer werden mit OnCalendar= konfiguriert, wie oben beschrieben.
Monotone Timer werden nach einer festgelegten Dauer ab einem bestimmten Ereignis aktiviert, wie dem Systemstart oder der Unit-Aktivierung. Die unterstützten Einheiten sind (N bedeutet eine beliebige Zahl)
1microsecond oder Nmicroseconds
1millisecond oder Nmilliseconds
1second oder Nseconds
1minute oder Nminutes
1hour oder Nhours
1day oder Ndays
1week oder Nweeks
1month oder Nmonths
1year oder Nyears
Für singuläre Werte wie 1year können Sie das s in yearS weglassen. Die folgenden Optionen existieren zum Konfigurieren monotoner Timer:
Startet einen Timer, nachdem er aktiviert wurde, wie in systemctl activate test.timer:
OnActiveSec=3hours 10minutes 17seconds
Startet einen Timer relativ zum Booten der Maschine:
OnBootSec=2days 50seconds
Startet einen Timer, nachdem systemd selbst gestartet wurde - dies ist üblicherweise fast gleich OnBootSec=.
OnStartupSec=1minute 10seconds
Startet einen Timer relativ dazu, wann der Timer zuletzt aktiviert wurde:
OnUnitActiveSec=10seconds
Dies bedeutet, dass nach Ausführung von:
systemctl enable test.timer
Der Timer 10 Sekunden später ausgeführt wird.
Startet einen Timer relativ dazu, wann der systemd-Service, den er starten soll, zuletzt gestoppt wurde. Wenn wir ein Skript ausführen, das 5 Sekunden läuft, dann würde das folgende Beispiel den Timer 45 Sekunden später erneut ausführen:
OnUnitInactiveSec=45seconds
Transiente Timer funktionieren nur, während Ihre Sitzung geöffnet ist - also während Sie mit dem aktuellen Linux-Benutzer angemeldet sind. Wenn Sie sich per SSH mit einem Server verbinden und einen transienten Timer starten und sich dann wieder abmelden, wird er nicht ausgeführt. Sie können jedoch Folgendes ausführen:
loginctl enable-linger <username>
um die Sitzung des Benutzers im Hintergrund aktiv zu lassen, nachdem Sie sich abgemeldet haben.
Um transiente Timer zu erstellen, wird der Befehl systemd-run verwendet.
Führen Sie den systemd-Service test.service in 10 Minuten aus:
systemd-run --on-active="10minutes" --unit="test.service"
Sie können auch einen Befehl oder ein Skript direkt ausführen. Alles nach dem auszuführenden Befehl wird als Argument für diesen Befehl oder dieses Skript betrachtet:
systemd-run --on-active="55minutes" /root/test.sh
systemd-run --on-active="55minutes" /root/test.sh --arg1 --arg2
Das Tool systemd-run akzeptiert die Argumente, die den Argumenten ähneln, die eine Systemd-Timer-Konfigurationsdatei akzeptiert, wie --on-active=, --on-startup=, --on-calendar=, --on-clock-change und ähnliche. Weitere Informationen finden Sie unter man systemd-run.
Die folgenden Konfigurationsoptionen können verwendet werden, um systemd-Timer bei Änderungen der Uhr auszulösen. Ich bin nicht sicher, wie nützlich das ist… Aber es ist Teil der Systemd-Timer.
boolean, Standard: false
Aus man systemd.timer: “Wenn true, wird die Service-Unit ausgelöst, wenn die Systemuhr (CLOCK_REALTIME) relativ zur monotonen Uhr (CLOCK_MONOTONIC) springt”.
date
verwenden. Sie können sie manuell oder mit NTP anpassen.Dies bedeutet, dass dieser Timer ausgelöst wird, wenn eine manuelle Aktualisierung der Systemzeit vorgenommen wird. Aus der Manualpage könnte man annehmen, dass dies auch für die regulären Updates gelten würde, die über NTP durchgeführt werden, wie durch die Verwendung von ntpdate, ntpd oder systemd-timesyncd, jedoch konnte ich dies nicht reproduzieren. Die einzige Möglichkeit, wie ich dies auslösen konnte, war durch manuelles erzwungenes Setzen der Zeit, wie im folgenden Beispiel gezeigt:
Ein Systemd-Timer, der OnClockChange=true als Trigger verwendet:
[Unit]
Description=Execute the BASH script /root/test.sh
[Timer]
OnClockChange=true
[Install]
WantedBy=timers.target
Der systemd-Service, den dieser Timer auslöst:
[Unit]
Description=MyScript Service
[Service]
Type=oneshot
ExecStart=/root/test.sh
Das BASH-Skript, das der Service ausführt:
#!/bin/bash
echo "I am a test script executing at $(date)" | tee -a /root/test.log
NTP für das System deaktivieren:
timedatectl set-ntp false
Manuelles Setzen der Zeit:
date -s '2019-10-17 12:00:00'
Do 17. Okt 12:00:00 UTC 2019
Das folgende Ergebnis zeigt, dass der Timer ausgelöst wurde, der den Dienst startete, der das BASH-Skript ausführte:
cat /root/test.log
I am a test script executing at Do 17. Okt 12:00:00 UTC 2019
NTP wieder aktivieren:
timedatectl set-ntp true
Das Zurückschalten auf die von NTP verwaltete Zeit löste ebenfalls den Systemd-Timer aus:
cat /root/test.log
I am a test script executing at Do 17. Okt 12:00:00 UTC 2019
I am a test script executing at Mi 17. Apr 21:02:13 UTC 2024
boolean, Standard: false
Führt den Timer aus, wenn Sie eine neue Zeitzone festlegen:
OnTimezoneChange=true
Ändern Sie die Zeitzone mit dem folgenden Befehl, um den Timer auszulösen:
timedatectl set-timezone America/New_York
Die folgenden Konfigurationsoptionen können verwendet werden, um systemd-Timer zu zufälligen Zeiten innerhalb eines definierbaren Zeitrahmens auszuführen.
Standard: 1min
Diese Konfigurationsoption ist sehr wichtig zu verstehen, wenn Sie einen Timer genau zu einer bestimmten Zeit ausführen möchten, bis auf die Sekunde genau.
Standardmäßig werden systemd-Timer NICHT GENAU zur angegebenen Zeit ausgeführt, sondern innerhalb einer Abweichung von AccuracySec=, die standardmäßig eine Minute beträgt!
Das bedeutet, wenn Sie einen Timer für die Ausführung um OnCalendar=21:00:00 einstellen, wird er möglicherweise nicht genau um 21:00:00 ausgeführt, sondern irgendwo zwischen 21:00:00 und 21:01:00, es sei denn, Sie haben die Einstellung AccuracySec= angepasst, die standardmäßig eine Minute beträgt.
Hier ist ein Beispiel: ein systemd-Timer, der so eingestellt ist, dass er alle 15 Sekunden ausgeführt wird:
cat /etc/systemd/system/test.timer
[Unit]
Description=Execute the BASH script /root/test.sh every 15 seconds
[Timer]
OnCalendar=*:*:0/15
[Install]
WantedBy=timers.target
Wenn wir uns die Protokolle ansehen, können wir sehen, dass das Skript nicht genau alle 15 Sekunden ausgeführt wird, sondern bei jeder Ausführung eine Abweichung von einigen zusätzlichen Sekunden aufweist:
journalctl -n 0 -f _SYSTEMD_UNIT=test.service
Apr 17 22:02:16 host test.sh[3536562]: I am a test script executing at Mi 17. Apr 22:02:16 UTC 2024
Apr 17 22:02:31 host test.sh[3536572]: I am a test script executing at Mi 17. Apr 22:02:31 UTC 2024
Apr 17 22:02:48 host test.sh[3536576]: I am a test script executing at Mi 17. Apr 22:02:48 UTC 2024
Apr 17 22:03:05 host test.sh[3536657]: I am a test script executing at Mi 17. Apr 22:03:05 UTC 2024
Apr 17 22:03:18 host test.sh[3536695]: I am a test script executing at Mi 17. Apr 22:03:18 UTC 2024
Sie können dies mit AccuracySec=1s “beheben”:
cat /etc/systemd/system/test.timer
[Unit]
Description=Execute the BASH script /root/test.sh
[Timer]
OnCalendar=*:*:0/15
AccuracySec=1
[Install]
WantedBy=timers.target
Wie Sie in den folgenden Ergebnissen sehen können, ist die Ausführungszeit jetzt vollkommen genau:
journalctl -n 0 -f _SYSTEMD_UNIT=test.service
Apr 17 22:00:00 host test.sh[3536066]: I am a test script executing at Mi 17. Apr 22:00:00 UTC 2024
Apr 17 22:00:15 host test.sh[3536136]: I am a test script executing at Mi 17. Apr 22:00:15 UTC 2024
Apr 17 22:00:30 host test.sh[3536142]: I am a test script executing at Mi 17. Apr 22:00:30 UTC 2024
Apr 17 22:00:45 host test.sh[3536168]: I am a test script executing at Mi 17. Apr 22:00:45 UTC 2024
Apr 17 22:01:00 host test.sh[3536270]: I am a test script executing at Mi 17. Apr 22:01:00 UTC 2024
Die Manualpage man systemd.timer besagt: “Um die beste Genauigkeit zu erzielen, setzen Sie diese Option auf 1us” - ich konnte keine besseren Ergebnisse erzielen, indem ich dies auf einen niedrigeren Wert als 1 Sekunde setzte. Der Grund für dieses Verhalten oder für den Standardwert von einer Minute ist laut Manualpage: “um den Stromverbrauch zu optimieren, um unnötige CPU-Aufwachvorgänge zu unterdrücken”.
Wenn Sie von Cron migrieren, wird dieses Verhalten für die meisten Benutzer höchstwahrscheinlich sehr verwirrend (und unentdeckt) sein. Da Sie höchstwahrscheinlich wiederkehrende Jobs auf einem Server ausführen (wo Sie sich nicht um den marginal winzigen zusätzlichen Stromverbrauch von systemd-Timern neben Ihrer glühend heißen Datenbank oder PHP-Anwendung kümmern), würde ich empfehlen, diese Einstellung in allen von Ihnen konfigurierten systemd-Timern zu definieren und auf 1 Sekunde zu setzen.
Wenn Sie Programme auf mehreren Maschinen in Ihrem Cluster ausführen müssen, aber nicht alle zur gleichen Zeit, ist diese Option für Sie. Sie wird die Ausführung des Timers einfach innerhalb des angegebenen Zeitrahmens randomisieren. Das folgende Beispiel führt den Timer jeden Tag zu einer zufälligen Zeit zwischen 00:00:00 und 00:10:00 aus.
Beachten Sie, dass das Sec in RandomizedDelaySec tatsächlich für Sekunden steht - wenn Sie RandomizedDelaySec=30 angeben, bedeutet das 30 Sekunden. Sie können auch RandomizedDelaySec=30seconds angeben, was dem einfachen Angeben von 30 entspricht, oder Sie können RandomizedDelaySec=5minutes oder Ähnliches angeben.
OnCalendar=0:0:0
RandomizedDelaySec=10minutes
Zur Verdeutlichung des 0:0:0:
faketime '1970-01-01 00:00:00' systemd-analyze calendar "0:0:0"
Original form: 0:0:0
Normalized form: *-*-* 00:00:00
Next elapse: Fri 1970-01-02 00:00:00 UTC
From now: 23h left
Beachten Sie, dass in dieser Konstellation der Wert von AccuracySec=, wie oben beschrieben , ebenfalls wichtig sein könnte. AccuracySec= ist standardmäßig eine Minute. Wenn Sie RandomizedDelaySec=5minutes für einen systemd-Timer definieren, der täglich um 00:00:00 ausgeführt werden soll, wird er zwischen 00:00:00 und 00:06:00 ausgeführt. Um dies zu verhindern, setzen Sie AccuracySec=1 (eine Sekunde). Das Handbuch (oft) empfiehlt, AccuracySec=1us (eine Mikrosekunde) zu setzen, was meiner Meinung nach keinen Sinn macht und genau das Gegenteil von dem erreicht, wofür AccuracySec= entwickelt wurde - unnötige CPU-Aufwachvorgänge zu verhindern. Informationen zur besten Ausführung von Aufgaben häufiger als einmal pro Minute finden Sie unter Starten eines Systemd-Timers alle paar Sekunden - Die bessere Alternative .
boolean, Standard: false
Diese boolesche Konfigurationsoption gibt an, ob die Randomisierungszeit über Neustarts hinweg festgelegt ist. Wenn Sie dies auf true setzen, wird das zufällige Intervall immer identisch sein. Das Setzen von RandomizedDelaySec=0 deaktiviert dies. Der Standardwert ist false.
Die genaue zufällige Zeit, die systemd zur Ausführung Ihres Timers wählt, kann in diesem Blogbeitrag offensichtlich nicht vorhergesagt werden. Aus man systemd.timer: “Die Verschiebung hängt von der Maschinen-ID, der Benutzerkennung und dem Timernamen ab”. Daher ist das folgende Beispiel nur zum besseren Verständnis gedacht - wir können davon ausgehen, dass das folgende Beispiel den Timer IMMER um 00:07:31 ausführen wird, auch nach einem Neustart.
OnCalendar=daily
RandomizedDelaySec=10minutes
FixedRandomDelay=true
Standardmäßig würde ein Timer /etc/systemd/systemd/test.timer einen systemd-Service /etc/systemd/system/test.service aktivieren. Um dieses Verhalten zu überschreiben, können Sie die Unit= wie folgt angeben:
Unit=my_test
Was /etc/systemd/system/my_test.service aktivieren würde. Ich empfehle nicht, von der Standardeinstellung abzuweichen, indem Sie diese Option verwenden, da dies Ihre Konfiguration unter /etc/systemd/system/ nur verwirrender macht.
boolean, Standard: false
Diese boolesche Konfigurationsoption gilt nur für mit OnCalendar= konfigurierte Timer. Wenn ein Timer während eines Systemausfalls ausgelöst werden sollte, wird er ausgeführt, sobald das System wieder online ist. Wenn auf false gesetzt, wird der Timer nicht ausgeführt, sobald die Maschine startet. Wenn er mehrere Ausführungen verpasst hat, während das System ausgeschaltet war oder anderweitig nicht betriebsbereit war, wird er nur einmal ausgeführt.
Das Setzen auf true speichert die letzte Ausführungszeit auf der Festplatte. Diese Datei wird in /var/lib/systemd/timers/stamp-test.timer für eine systemd-Timer-Datei namens /etc/systemd/system/test.timer gespeichert. Der Zeitstempel wird nicht tatsächlich in der Datei gespeichert, sondern die Änderungszeit der Datei wird einfach aktualisiert. Hier sind die Zeitstempel für eine solche Datei für einen Systemd-Timer mit Persistent=true, der so konfiguriert ist, dass er einmal pro Sekunde ausgeführt wird:
while true; do ls -la --time-style=full-iso /var/lib/systemd/timers/stamp-test.timer; sleep 1; done
-rw-r--r-- 1 root root 0 2024-04-18 00:44:36.096114000 +0000 /var/lib/systemd/timers/stamp-test.timer
-rw-r--r-- 1 root root 0 2024-04-18 00:44:37.831349000 +0000 /var/lib/systemd/timers/stamp-test.timer
-rw-r--r-- 1 root root 0 2024-04-18 00:44:38.831427000 +0000 /var/lib/systemd/timers/stamp-test.timer
-rw-r--r-- 1 root root 0 2024-04-18 00:44:39.831595000 +0000 /var/lib/systemd/timers/stamp-test.timer
Sie können systemctl clean --what=state test.timer verwenden, um diese Zeitstempeldatei zu löschen. Das Handbuch man systemd.timer empfiehlt, dass Sie diesen Befehl ausführen, bevor Sie einen Timer deinstallieren, der mit Persistent=true konfiguriert wurde. Wenn Sie einen Timer nur stoppen und deaktivieren, wird diese Datei nicht entfernt.
boolean, Standard: false
Diese Konfigurationsoption ist weniger für Server als für Workstations gedacht: Wenn sich Ihre Workstation im Ruhezustand befindet (Suspend to Disk oder Suspend to RAM), bewirkt das Setzen dieser Option auf true, dass Ihre Maschine aufwacht und den Timer ausführt. (Hinweis: Ich habe dies nicht getestet und gehe davon aus, dass dies etwas Debugging erfordern wird). Beachten Sie auch, dass sie nach der Ausführung des Timers nicht wieder in den Ruhezustand versetzt wird. Beachten Sie außerdem, dass dies nur funktioniert, wenn der systemd-Timer als Root-Benutzer konfiguriert ist.
Wenn false, verwendet der Timer eine monotone Uhr namens “CLOCK_MONOTONIC”, die während eines suspendierten Systems angehalten wird. CLOCK_MONOTONIC wird beim Systemstart gestartet und zählt die Zeit seitdem. Weitere Informationen finden Sie unter man clock_gettime und suchen Sie nach “CLOCK_MONOTONIC”.
Wenn true, verwendet der Timer die monotone Uhr “CLOCK_BOOTTIME”, die ähnlich wie CLOCK_MONOTONIC ist, außer dass sie weiterläuft, wenn das System suspendiert ist. Aus diesem Grund können systemd-Timer auch dann ausgelöst werden, wenn das System suspendiert ist. Weitere Informationen finden Sie unter man clock_getres und suchen Sie nach “CLOCK_BOOTTIME”.
boolean, Standard: true
Systemd-Timer sprechen oft von “abgelaufenen Timern” - das bedeutet, dass die Zeit bis zum Auslösen des systemd-Timers “abgelaufen” ist - was bedeutet, dass es jetzt an der Zeit ist, den systemd-Service zu aktivieren, für den der systemd-Timer konfiguriert ist.
Wenn auf false gesetzt, wird diese Konfigurationsoption einen systemd-Timer nach seiner letzten konfigurierten Ausführung deaktivieren.
Der Unterschied zwischen einem aktiven und einem inaktiven Timer ist dieser:
systemctl status test.timer | grep Active
Active: active (waiting) since Wed 2024-04-17 20:32:59 UTC; 8s ago
systemctl stop test.timer
systemctl status test.timer | grep Active
Active: inactive (dead)
Im folgenden Beispiel habe ich einen OnCalendar-Wert verwendet, der den Timer nur eine endliche Anzahl von Malen auslöst. Ich habe dies mit OnCalendar=*:0/1:0 (einmal pro Minute) versucht und es hat nicht funktioniert - der Timer blieb aktiv und wurde weiter ausgeführt. Daher ist diese Option nützlich, um einen Timer zu deaktivieren, der eine begrenzte Anzahl von Malen ausgelöst wird und dann nie wieder, und nachdem alle möglichen Auslösezeiten vorbei sind, wird er den systemd-Timer automatisch deaktivieren.
Hier ist das Beispiel-systemd-Timer - es führt einen systemd-Service aus, der das BASH-Skript /root/test.sh alle 10 Sekunden von 21:30:00 bis 21:30:50 ausführt.
cat /etc/systemd/system/test.timer
[Unit]
Description=Execute the BASH script /root/test.sh
[Timer]
OnCalendar=2024-04-17 21:30:0/10
RemainAfterElapse=false
[Install]
WantedBy=timers.target
Beim ersten Anzeigen des Timer-Status um 21:29:53 - es heißt, er wird in 7 Sekunden ausgeführt:
systemctl status test.timer
● test.timer - Execute the BASH script /root/test.sh
Loaded: loaded (/etc/systemd/system/test.timer; enabled; preset: enabled)
Active: active (waiting) since Wed 2024-04-17 21:29:50 UTC; 1s ago
Until: Wed 2024-04-17 21:29:50 UTC; 1s ago
Trigger: Wed 2024-04-17 21:30:00 UTC; 7s left
Triggers: ● test.service
Ich habe jetzt eine Minute gewartet und der Timer wurde alle 10 Sekunden von 21:30:00 bis 21:30:50 ausgeführt. Danach hörte er auf, wie in seiner OnCalendar-Einstellung definiert, und deaktivierte sich auch um 21:30:56 selbst:
systemctl status test.timer
○ test.timer - Execute the BASH script /root/test.sh
Loaded: loaded (/etc/systemd/system/test.timer; enabled; preset: enabled)
Active: inactive (dead) since Wed 2024-04-17 21:30:56 UTC; 14s ago
Duration: 1min 6.515s
Trigger: n/a
Triggers: ● test.service
Apr 17 21:29:50 host systemd[1]: Started test.timer - Execute the BASH script /root/test.sh.
Apr 17 21:30:56 host systemd[1]: test.timer: Deactivated successfully.
Hier sind einige praktische Beispiele für die Planung von systemd-Timern. Bitte beziehen Sie sich auf die obige Beschreibung , wie Sie die systemd-Timer-Konfigurationsdateien dafür erstellen.
Der folgende Abschnitt enthält Beispiele für die Konfigurationsoption OnCalendar=. Bitte beziehen Sie sich auf die detaillierte Beschreibung zur Verwendung von OnCalendar= für alle Informationen zu seiner Syntax.
Um die Syntax Ihrer eigenen Konfigurationen von OnCalendar= zu überprüfen, können Sie das Tool systemd-analyze calendar verwenden. Alle folgenden Beispiele verwenden den Befehl faketime '1970-01-01 00:00:00' vor dem Befehl systemd-analyze calendar, um die Lesbarkeit bei der Identifizierung der verbleibenden Zeit für die Ausführung des systemd-Timers zu verbessern.
Wenn Sie Systemd-Timer verwenden möchten, die präzise zu einer bestimmten Sekunde ausgeführt werden, wie z. B. um 05:45:00 Uhr, lesen Sie auch diesen Abschnitt , wie Sie die standardmäßig hinzugefügte zufällige Zeit von +60 Sekunden zu jedem Timer deaktivieren können!
Beispiel:
OnCalendar="*:0/1:0"
Überprüfung:
faketime '1970-01-01 00:00:00' systemd-analyze calendar "*:0/1:0"
Original form: *:0/1:0
Normalized form: *-*-* *:00/1:00
Next elapse: Thu 1970-01-01 00:01:00 UTC
From now: 59s left
Wenn Sie Systemd-Timer verwenden möchten, die präzise zu einer bestimmten Sekunde ausgeführt werden, wie z. B. um 05:45:00 Uhr, lesen Sie auch diesen Abschnitt , wie Sie die standardmäßig hinzugefügte zufällige Zeit von +60 Sekunden zu jedem Timer deaktivieren können!
Beispiel:
OnCalendar="*:0/5:0"
Überprüfung:
faketime '1970-01-01 00:00:00' systemd-analyze calendar "*:0/5:0"
Original form: *:0/5:0
Normalized form: *-*-* *:00/5:00
Next elapse: Thu 1970-01-01 00:05:00 UTC
From now: 4min 59s left
Beispiel:
OnCalendar="hourly"
Überprüfung:
faketime '1970-01-01 00:00:00' systemd-analyze calendar "hourly"
Original form: hourly
Normalized form: *-*-* *:00:00
Next elapse: Thu 1970-01-01 01:00:00 UTC
From now: 59min left
Beispiel:
OnCalendar="0/2:0:0"
Überprüfung:
faketime '1970-01-01 00:00:00' systemd-analyze calendar "0/2:0:0"
Original form: 0/2:0:0
Normalized form: *-*-* 00/2:00:00
Next elapse: Thu 1970-01-01 02:00:00 UTC
From now: 1h 59min left
Beispiel:
OnCalendar="daily"
Überprüfung:
faketime '1970-01-01 00:00:00' systemd-analyze calendar "daily"
Original form: Mon..Sun
Normalized form: *-*-* 00:00:00
Next elapse: Fri 1970-01-02 00:00:00 UTC
From now: 23h left
Beispiel:
OnCalendar="Mon..Sun 14:30"
Überprüfung:
faketime '1970-01-01 00:00:00' systemd-analyze calendar "Mon..Sun 14:30"
Original form: Mon..Sun 14:30
Normalized form: *-*-* 14:30:00
Next elapse: Thu 1970-01-01 14:30:00 UTC
From now: 14h left
Die Angabe “weekly” führt den Timer jeden Montag um 00:00:00 aus. Beispiel:
OnCalendar="weekly"
Überprüfung:
faketime '1970-01-01 00:00:00' systemd-analyze calendar "weekly"
Original form: weekly
Normalized form: Mon *-*-* 00:00:00
Next elapse: Mon 1970-01-05 00:00:00 UTC
From now: 3 days left
Das folgende Beispiel ist möglicherweise praktischer und führt den Timer jeden Dienstag um 8 Uhr morgens aus:
OnCalendar="Tue 8:00"
Überprüfung:
faketime '1970-01-01 00:00:00' systemd-analyze calendar "Tue 8:00"
Original form: Tue 8:00
Normalized form: Tue *-*-* 08:00:00
Next elapse: Tue 1970-01-06 08:00:00 UTC
From now: 5 days left
Der beste Weg, einen systemd-Timer nach dem Booten der Maschine zu starten, ist die Verwendung der Konfigurationsoption OnStartupSec=, die den Timer innerhalb des angegebenen Zeitraums startet, nachdem systemd selbst zum ersten Mal gestartet wurde:
OnBootSec="10 seconds"
Dieses Beispiel beschreibt, wie ein systemd-Service regelmäßig mit einem systemd-Timer neu gestartet wird.
Systemd-Timer selbst (die .timer-Dateien) sind nur für das Timing zum STARTEN von systemd-Services verantwortlich - wenn ein Timer seine konfigurierte Zeit zur Ausführung erreicht, führt er ein systemctl start some.service aus.
Sie können jedoch einfach einen OneShot-Service erstellen, der einen systemctl-Befehl ausführt, wie systemctl restart php8.4-fpm.service. Das Starten dieses speziellen Service würde dann einen anderen Service neu starten.
Um einen systemd-Service mit einem systemd-Timer neu zu starten, müssen wir sowohl eine .timer- als auch eine .service-Datei erstellen - wobei die .service-Datei einen einzigen systemctl-Befehl enthält, um den eigentlichen Service neu zu starten, den wir neu starten möchten.
Hier ist ein vollständiges Beispiel, das den systemd-Service php8.4-fpm alle zwei Stunden mit einem systemd-Timer neu startet.
Speichern Sie Folgendes in /etc/systemd/system/restart-php-fpm.timer:
[Unit]
Description=Trigger the systemd service restart-php-fpm.service every two hours
[Timer]
OnCalendar=*-*-* 0/2:00:00
[Install]
WantedBy=timers.target
Und erstellen Sie einen systemd-Service vom Typ OneShot, um tatsächlich den Befehl systemctl restart php8.4-fpm.service auszuführen. Speichern Sie den folgenden Inhalt in /etc/systemd/system/restart-php-fpm.service:
[Unit]
Description=Restart the systemd service php8.4-fpm.service
[Service]
Type=oneshot
ExecStart=/bin/systemctl restart php8.4-fpm.service
Um die Änderungen an den systemd-Konfigurationsdateien unter /etc/systemd/system/ anzuwenden:
systemctl daemon-reload
Um den Timer zu aktivieren:
systemctl enable restart-php-fpm.timer
Created symlink /etc/systemd/system/timers.target.wants/restart-php-fpm.timer → /etc/systemd/system/restart-php-fpm.timer.
Um den Status des Timers anzuzeigen:
systemctl status restart-php-fpm.timer
● restart-php-fpm.timer - Trigger the systemd service restart-php-fpm.service every two hours
Loaded: loaded (/etc/systemd/system/restart-php-fpm.timer; enabled; preset: enabled)
Active: active (waiting) since Tue 2024-04-16 22:00:01 UTC; 4ms ago
Until: Tue 2024-04-16 22:00:01 UTC; 4ms ago
Trigger: Wed 2024-04-17 00:00:00 UTC; 1h 59min left
Triggers: ● restart-php-fpm.service
Wenn Sie den Timer testen möchten, können Sie ihn “starten” - beachten Sie, dass “enable” bedeutet, den Timer zu aktivieren, also darauf zu warten, dass seine Ausführungszeit erreicht wird, und “start” bedeutet, den Timer tatsächlich auszuführen, unabhängig davon, was Sie für seine Ausführungszeit mit OnCalendar= konfiguriert haben:
systemctl start restart-php-fpm.timer
# Dieser Befehl gibt bei erfolgreicher Ausführung keine Ausgabe aus
Weitere Informationen zum Überprüfen der journalctl-Protokolle, ob der systemd-Timer erfolgreich ausgeführt wurde, finden Sie im Debugging-Abschnitt dieses Blogposts
.
Wie im Abschnitt unten beschrieben, wie man das besser macht , halte ich die Verwendung von systemd-Timern zur Ausführung eines systemd-Service häufiger als einmal pro Minute nicht für einen guten Ansatz. Es ist jedoch mit Systemd-Timern möglich, und hier ist eine vollständige Beschreibung, wie man dies korrekt und sekundengenau macht.
Bei der Ausführung von systemd-Timern in einem Sekundenintervall sind mehrere Dinge zu beachten. Erstens, wie im AccuracySec=-Abschnitt beschrieben, halten sich systemd-Timer nicht auf die Sekunde genau an die von Ihnen angegebene Zeit, z. B. mit OnCalendar=, es sei denn, Sie konfigurieren es explizit. Die Einstellung AccuracySec= hat einen Standardwert von einer Minute, was bedeutet, dass systemd den Timer mit einer Abweichung von plus einer Minute ausführt - wenn Sie einen Timer für 00:00:00 einstellen, wird er zwischen 00:00:00 und 00:01:00 ausgeführt.
Bis zur Ausführung eines Timers alle 15 Sekunden kann dieses Verhalten durch Setzen von AccuracySec=1second “behoben” werden. Ein systemd-Timer wie OnCalendar=*:*:0/15 wird dann zuverlässig alle 15 Sekunden auf die Sekunde genau ausgeführt. Bei der Angabe eines Ausführungsintervalls von weniger als 15 Sekunden habe ich beim Schreiben dieses Blogposts weitere Schwierigkeiten festgestellt (lesen Sie weiter für die Lösung).
Das erste Problem, auf das ich stieß, ist, dass systemd anfängt, sich zu beschweren, wenn Sie einen systemd-Service zu oft neu starten - da systemd-Timer einfach systemd-Services auslösen, gilt dies und löst die folgende Fehlermeldung aus. Konfigurieren wir OnCalendar so, dass es alle 5 Sekunden ausgeführt wird:
OnCalendar="*:*:0/5"
Resultierende Fehlermeldung:
root@host:~# journalctl -f --identifier systemd
Apr 18 00:09:46 host systemd[1]: test.service: Start request repeated too quickly.
Apr 18 00:09:46 host systemd[1]: test.service: Failed with result 'start-limit-hit'.
Apr 18 00:09:46 host systemd[1]: Failed to start test.service - MyScript Service.
Laut diesem Stackoverflow-Post
ist das “Standardlimit, 5 Neustarts in einem Zeitraum von 10 Sekunden zu erlauben. Wenn ein Dienst diese Schwelle aufgrund der Restart=-Konfigurationsoption in der Dienstdefinition überschreitet, wird er keine weiteren Neustarts versuchen.” Mit dem Starten eines Dienstes alle 5 Sekunden sollten wir jedoch darunter liegen. Unabhängig davon hier ist die Lösung, wie man einen systemd-Timer einmal pro Sekunde verwendet. Aus man systemd.unit:
StartLimitIntervalSec=interval, StartLimitBurst=burst
Configure unit start rate limiting. Units which are started more than burst times within an interval time span are not permitted to start any more.
Use StartLimitIntervalSec= to configure the checking interval and StartLimitBurst= to configure how many starts per interval are allowed.
Wenn der systemd-Service, den wir einmal pro Sekunde mit dem Timer starten möchten, so konfiguriert wird:
[Unit]
Description=MyScript Service
[Service]
Type=oneshot
ExecStart=/root/test.sh
StartLimitIntervalSec=1
StartLimitBurst=10
konnte ich den systemd-Timer zuverlässig einmal pro Sekunde auslösen. Hier ist die Timer-Datei, die ich verwendet habe:
[Unit]
Description=Execute the BASH script /root/test.sh
[Timer]
OnCalendar=*:*:0/1
AccuracySec=1
[Install]
WantedBy=timers.target
Hier ist das Ergebnis:
root@host:~# journalctl -f --identifier test.sh
Apr 18 00:32:55 host test.sh[3570468]: I am a test script executing at Do 18. Apr 00:32:55 UTC 2024
Apr 18 00:32:56 host test.sh[3570472]: I am a test script executing at Do 18. Apr 00:32:56 UTC 2024
Apr 18 00:32:57 host test.sh[3570476]: I am a test script executing at Do 18. Apr 00:32:57 UTC 2024
Apr 18 00:32:58 host test.sh[3570480]: I am a test script executing at Do 18. Apr 00:32:58 UTC 2024
Apr 18 00:32:59 host test.sh[3570485]: I am a test script executing at Do 18. Apr 00:32:59 UTC 2024
Wie Sie sehen können, führt der Systemd-Timer seinen zugewiesenen Dienst nun zuverlässig einmal pro Sekunde ohne Fehler aus.
Die Verwendung von systemd-Timern zur Ausführung eines systemd-Service alle paar Sekunden ist meiner Meinung nach kein guter Ansatz - was Sie höchstwahrscheinlich tun möchten, ist, ein Programm oder einen Daemon zu schreiben, der Ihre Aufgabe im gewünschten Sekundenintervall ausführt. Das einfachste Beispiel in einem BASH-Skript wäre:
cat << EOF > /usr/local/bin/my-daemon.sh
#!/bin/bash
while true; do
echo "Do things"
sleep 5
done
EOF
Machen Sie das Skript ausführbar:
chmod 700 /usr/local/bin/my-daemon.sh
Sie können dafür einen systemd-Service wie folgt einrichten:
cat << EOF > /etc/systemd/system/my-daemon.service
[Unit]
Description=My Daemon Service
After=syslog.target
[Service]
Type=simple
ExecStart=/usr/local/bin/my-daemon.sh
Restart=always
SyslogIdentifier=my-daemon
[Install]
WantedBy=multi-user.target
EOF
Laden Sie den systemd-Daemon neu, um die Änderungen zu übernehmen:
systemctl daemon-reload
Und starten Sie den Dienst:
systemctl start my-daemon.service
Dies verwendet SyslogIdentifier=my-daemon im systemd-Service, um einen eindeutigen Syslog-Identifier festzulegen, den wir nun verwenden können, um die Protokolle nur für diesen Dienst mit journalctl zu filtern:
journalctl -f --identifier my-daemon
Apr 18 00:00:00 host my-daemon[3564012]: Do things
Apr 18 00:00:05 host my-daemon[3564012]: Do things
Apr 18 00:00:10 host my-daemon[3564012]: Do things
Apr 18 00:00:15 host my-daemon[3564012]: Do things
Apr 18 00:00:20 host my-daemon[3564012]: Do things
Systemd ermöglicht es Ihnen, Abhängigkeiten zu anderen Systemd-Timern oder Systemd-Services mit den Konfigurationsoptionen Requires=, After= und Wants= zu definieren:
Requires=
Die Requires=-Direktive gibt andere Units an, die von der aktuellen Unit benötigt werden
Wenn die in Requires= angegebenen Units nicht aktiv sind, wird systemd versuchen, sie zu aktivieren, wenn die aktuelle Unit gestartet wird
Wenn eine der erforderlichen Units nicht aktiviert werden kann oder nicht verfügbar ist, schlägt auch der Start der aktuellen Unit fehl
Die Requires=-Direktive erzeugt eine starke Abhängigkeit zwischen Units und stellt sicher, dass sie zusammen gestartet und gestoppt werden
After=
Die After=-Direktive gibt andere Units an, die vor der aktuellen Unit gestartet werden sollen
Sie impliziert keine Abhängigkeitsbeziehung wie Requires=. Stattdessen gibt sie nur die Reihenfolge an, in der Units gestartet werden sollen
In After= aufgeführte Units können gleichzeitig mit der aktuellen Unit aktiviert werden oder auch nicht.
Verwenden Sie After=, um die Reihenfolge der Unit-Aktivierung zu steuern, um sicherzustellen, dass bestimmte Units vor anderen gestartet werden, ohne eine strikte Abhängigkeit zu schaffen
Wants=
Die Wants=-Direktive gibt andere Units an, mit denen die aktuelle Unit gestartet werden möchte, die aber nicht zwingend erforderlich sind
Im Gegensatz zu Requires= verhindert das Nichtstarten von in Wants= aufgeführten Units nicht den Start der aktuellen Unit
In Wants= aufgeführte Units werden nach Möglichkeit gestartet, aber ihr Nichtstarten beeinflusst die aktuelle Unit nicht
Wants= erzeugt eine schwächere Abhängigkeit im Vergleich zu Requires=, die es Units ermöglicht, unabhängig, aber wenn möglich gemeinsam zu starten
Hier ist ein Beispiel mit zwei systemd-Timer-Units: test1.timer und test2.timer. Wir möchten, dass test2.timer erst startet, nachdem test1.timer seinen zugewiesenen systemd-Service erfolgreich beendet hat.
Der erste Timer /etc/systemd/system/timer1.timer ist nur ein einfacherer Timer, der so konfiguriert ist, dass er täglich um 00:00:00 startet:
# timer1.timer
[Unit]
Description=Timer 1
[Timer]
OnCalendar=0:0:0
Persistent=true
[Install]
WantedBy=timers.target
Der zweite Timer ist so eingestellt, dass er um 01:00:00 startet. Er verwendet jedoch auch Requires=timer1.timer und After=timer1.timer.
# timer2.timer
[Unit]
Description=Timer 2
Requires=timer1.timer
After=timer1.timer
[Timer]
OnCalendar=1:0:0
Persistent=true
[Install]
WantedBy=timers.target
Das bedeutet, dass:
Wenn timer1 die Ausführung seines zugewiesenen systemd-Service um 01:15:00 erfolgreich beendet, startet timer2 um 01:15:00 und nicht um 01:00:00
Wenn der zugewiesene systemd-Service von timer1 während seiner Ausführung fehlschlägt, wird timer2 nicht ausgeführt
Hier sind einige Informationen, die Ihnen beim Debuggen von Systemd-Timern hilfreich sein könnten.
Systemd-Timer-Units können nicht nur als Linux-Root-Benutzer konfiguriert werden - auch unprivilegierte Linux-Benutzer können sie verwenden. Hier ist, wie man einen beispielhaften Systemd-Timer als regulärer Linux-Benutzer erstellt.
Erstellen Sie zuerst ein Konfigurationsverzeichnis:
mkdir -p ~/.config/systemd/user/
Erstellen Sie nun eine Timer-Unit-Konfigurationsdatei:
cat << EOF > ~/.config/systemd/user/test.timer
[Unit]
Description=Start the non-root user Systemd service test.service every 10 minutes
[Timer]
OnCalendar=*:0/10:*
Persistent=true
[Install]
WantedBy=timers.target
EOF
Erstellen Sie nun eine Systemd-Service-Datei:
cat << EOF > ~/.config/systemd/user/test.service
[Unit]
Description=Execute the BASH script /root/test.sh
[Service]
Type=oneshot
ExecStart=/bin/echo teststring
EOF
Um den Timer zu aktivieren, laden Sie zuerst systemd neu, um die neue Konfiguration zu akzeptieren:
systemctl --user daemon-reload
Und aktivieren Sie dann den Timer:
systemctl --user enable test.timer
Wichtig: Benutzer-Timer laufen nur während einer aktiven Sitzung! Um Systemd-Timer nach dem Ausloggen weiterlaufen zu lassen, verwenden Sie dies:
sudo loginctl enable-linger <user>
Da Systemd-Timer nur Systemd-Services starten, können Sie einfach den systemd-Service, den der Timer starten soll, so konfigurieren, dass er als bestimmter Benutzer und Gruppe ausgeführt wird:
[Unit]
Description=Your Service
[Service]
Type=simple
ExecStart=/path/to/your/command
User=your_username
Group=your_groupname
[Install]
WantedBy=multi-user.target
Um mehr Iterationen in systemd-analyze calendar anzuzeigen, verwenden Sie --iterations=N:
systemd-analyze calendar "Sat,Sun 13:0 Europe/Berlin" --iterations=4
Original form: Sat,Sun 13:0 Europe/Berlin
Normalized form: Sat,Sun *-*-* 13:00:00 Europe/Berlin
Next elapse: Sat 2024-04-20 11:00:00 UTC
From now: 3 days left
Iter. #2: Sun 2024-04-21 11:00:00 UTC
From now: 4 days left
Iter. #3: Sat 2024-04-27 11:00:00 UTC
From now: 1 week 3 days left
Iter. #4: Sun 2024-04-28 11:00:00 UTC
From now: 1 week 4 days left
Um die Lesbarkeit mit systemd-analyze calendar zu verbessern, können Sie faketime verwenden, um eine bestimmte Zeit für alle folgenden Befehle zu simulieren:
faketime 'last Friday 5 pm' systemd-analyze calendar "Sat,Sun 13:0 Europe/Berlin"
Original form: Sat,Sun 13:0 Europe/Berlin
Normalized form: Sat,Sun *-*-* 13:00:00 Europe/Berlin
Next elapse: Sat 2024-04-13 11:00:00 UTC
From now: 17h left
Siehe man faketime für weitere Informationen.
Hier sind einige Informationen, die Ihnen beim Debuggen Ihrer Systemd-Timer helfen könnten.
Beim Aktivieren eines Timers, der nicht-kritische Fehler enthält, ignoriert systemd diese stillschweigend! Zum Beispiel:
[Unit]
Description=Start the Systemd service test.service every 10 minutes
[Timer]
OnClendar=*:0/10:*
<== BEACHTEN SIE DEN FEHLENDEN BUCHSTABEN a IN Clendar
Persistent=true
[Install]
WantedBy=timers.target
Stellen Sie sicher, dass Sie Ihre Systemd-Unit-Dateien mit diesem Befehl überprüfen:
systemd-analyze verify /etc/systemd/system/test.timer
/etc/systemd/system/test.timer:5: Unknown key name 'OnClendar' in section 'Timer', ignoring.
test.timer: Timer unit lacks value setting. Refusing.
Unit test.timer has a bad unit file setting.
Beispiel journalctl-Logs:
journalctl -f
Apr 20 00:54:42 host systemd[1]: /etc/systemd/system/test.timer:5: Unknown key name 'OnClendar' in section 'Timer', ignoring.
Apr 20 00:54:42 host systemd[1]: test.timer: Timer unit lacks value setting. Refusing.
Um alle konfigurierten und aktiven Systemd-Timer aufzulisten:
systemctl list-timers
NEXT LEFT LAST PASSED UNIT ACTIVATES
Sat 2024-04-20 02:51:31 UTC 2h 2min left Fri 2024-04-19 11:48:43 UTC 13h ago plocate-updatedb.timer plocate-updatedb.service
Sat 2024-04-20 06:59:18 UTC 6h left Fri 2024-04-19 11:48:43 UTC 13h ago apt-daily-upgrade.timer apt-daily-upgrade.service
Sat 2024-04-20 07:33:29 UTC 6h left Sat 2024-04-20 00:24:10 UTC 25min ago anacron.timer anacron.service
[...]
Um auch inaktive Timer aufzulisten:
systemctl list-timers --all
NEXT LEFT LAST PASSED UNIT ACTIVATES
[...]
- - - - apport-autoreport.timer apport-autoreport.service
- - - - restart-php-fpm.timer
- - - - snapd.snap-repair.timer snapd.snap-repair.service
Um alle Systemd-Timer aufzulisten, die einem bestimmten Wildcard entsprechen:
systemctl list-timers apt*
NEXT LEFT LAST PASSED UNIT ACTIVATES
Sat 2024-04-20 06:59:18 UTC 6h left Fri 2024-04-19 11:48:43 UTC 13h ago apt-daily-upgrade.timer apt-daily-upgrade.service
Sat 2024-04-20 10:20:51 UTC 9h left Fri 2024-04-19 20:32:56 UTC 4h 17min ago apt-daily.timer apt-daily.service
2 timers listed.
Im Gegensatz zu Systemd-Services, die eine SyslogIdentifier=-Einstellung bieten, haben Timer selbst keine solche Einstellung und protokollieren immer mit dem “syslog”-Identifier. Um alle Protokolle aus dem Journal anzuzeigen, die dem Syslog-Feld entsprechen:
journalctl -f _COMM=systemd
Suchen Sie
Linux Notfallunterstützung,
Linux-Beratung für Projekte,
Linux Managed Hosting,
Qubes OS Beratung und Support oder
Online- und Vor-Ort-Schulungen?