Wie man systemd Timer-Units erstellt und verwaltet

Erstellen, aktivieren, überwachen und beheben Sie Probleme mit Systemd-Timer-Einheiten anhand praktischer Beispiele für `.timer`, `.service`, `systemctl` und `journalctl`.

So erstellen und verwalten Sie Systemd-Timer-Einheiten

Systemd-Timer-Einheiten planen Aufgaben unter Linux, ohne auf Cron angewiesen zu sein. Wenn Ihr Server ein Backup, einen Bereinigungsjob, einen Health-Check oder einen Bericht zu einem vorhersagbaren Zeitpunkt ausführen muss, bietet Ihnen ein Systemd-Timer Planung, Dienstisolierung, Abhängigkeitsverwaltung und Protokolle an einem Ort.

Die Kernidee ist einfach: Die .timer-Datei legt fest, wann etwas ausgeführt wird, und die .service-Datei legt fest, was ausgeführt wird. Diese Trennung macht Timer mit systemctl einfach zu überprüfen und mit journalctl einfach zu debuggen.

Die Struktur einer Systemd-Timer-Einheit verstehen

Eine Systemd-Timer-Einheit ist immer mit einer entsprechenden Service-Einheit (oder einem anderen Einheitentyp) gepaart, die sie aktivieren soll. Die Timer-Einheit selbst definiert, wann die zugehörige Einheit aktiviert werden soll, während die Service-Einheit definiert, welche Aktion ausgeführt werden soll. Beide Einheiten befinden sich normalerweise im selben Verzeichnis, oft /etc/systemd/system/ für benutzerdefinierte Einheiten.

Eine typische Timer-Einheitendatei hat die Erweiterung .timer, und die zugehörige Service-Einheitendatei hat die Erweiterung .service. Wenn Sie z. B. eine in mytask.service definierte Aufgabe planen möchten, erstellen Sie eine Datei mytask.timer.

Beispiel: mytask.timer

[Unit]
Description=Run my custom task daily

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target

Lassen Sie uns die wichtigsten Abschnitte aufschlüsseln:

  • Abschnitt [Unit]:

    • Description: Eine menschenlesbare Beschreibung des Timers. Dies hilft bei der Identifizierung in Statusausgaben.
  • Abschnitt [Timer]: Dies ist der Kern der Timer-Einheit und definiert die Planung.

    • OnCalendar=daily: Diese Direktive gibt an, wann der Timer aktiviert werden soll. daily ist eine Kurzform für Mitternacht eines jeden Tages. Weitere Beispiele sind:
      • hourly: Jede Stunde.
      • weekly: Jede Woche (entspricht Mon *-*-* 00:00:00).
      • Sun *-*-* 10:00: Jeden Sonntag um 10 Uhr.
      • *-*-15 14:30: Am 15. jedes Monats um 14:30 Uhr.
      • Mon..Fri *-*-* 09:00: An Wochentagen um 9 Uhr.
    • Persistent=true: Wenn dies auf true gesetzt ist, wird der Timer so schnell wie möglich aktiviert, wenn das Ereignis während der Systemabschaltung aufgetreten ist. Bei OnCalendar-Timern bedeutet dies, dass der Timer ausgelöst wird, sobald das System hochfährt und der Timer aktiv wird, wenn das System während der geplanten Zeit ausgeschaltet war.
    • OnBootSec=: Aktiviert den Timer eine bestimmte Zeit nach dem Systemstart. Zum Beispiel würde OnBootSec=15min 15 Minuten nach dem Start auslösen.
    • OnUnitActiveSec=: Aktiviert den Timer eine bestimmte Zeit, nachdem die von ihm aktivierte Einheit zuletzt aktiv wurde. Zum Beispiel plant OnUnitActiveSec=1h eine weitere Ausführung eine Stunde, nachdem der zugehörige Dienst zuletzt aktiviert wurde.
    • OnUnitInactiveSec=: Aktiviert den Timer eine bestimmte Zeit, nachdem die von ihm aktivierte Einheit zuletzt inaktiv wurde.
    • AccuracySec=: Gibt die Genauigkeit des Timers an. Systemd versucht, das System nur dann für Timer aufzuwecken, wenn das Ereignis innerhalb dieses Zeitfensters liegt, was zum Stromsparen beiträgt. Standard ist 1min.
    • RandomizedDelaySec=: Fügt dem Timer-Auslöser eine zufällige Verzögerung bis zur angegebenen Dauer hinzu. Nützlich zur Lastverteilung.
  • Abschnitt [Install]: Dieser Abschnitt definiert, wie die Timer-Einheit aktiviert werden kann.

    • WantedBy=timers.target: Diese Direktive stellt sicher, dass der Timer bei Aktivierung Teil des timers.target wird, einem Standard-Target, das alle aktiven Timer umfasst. Das bedeutet, dass der Timer nach der Aktivierung automatisch beim Booten startet.

Beispiel: mytask.service

[Unit]
Description=My custom task service

[Service]
Type=oneshot
ExecStart=/usr/local/bin/my_custom_script.sh
User=myuser
Group=mygroup

[Install]
WantedBy=multi-user.target
  • Abschnitt [Unit]:

    • Description: Eine Beschreibung des Dienstes.
  • Abschnitt [Service]: Dieser definiert den Dienst selbst.

    • Type=oneshot: Geeignet für Aufgaben, die einmal ausgeführt werden und dann beenden. Es gibt andere Typen für langlebige Daemons.
    • ExecStart: Der auszuführende Befehl. Stellen Sie sicher, dass das Skript Ausführungsberechtigungen hat.
    • User/Group: Gibt den Benutzer und die Gruppe an, unter denen der Befehl ausgeführt werden soll. Es ist gute Praxis, Aufgaben nicht als root auszuführen, es sei denn, es ist unbedingt erforderlich.
  • Abschnitt [Install]: Dieser Abschnitt wird normalerweise für einen Oneshot-Dienst nicht benötigt, der nur von einem Timer gestartet werden soll. Aktivieren Sie den Timer, nicht den Dienst.

Timer-Einheiten erstellen und aktivieren

Befolgen Sie diese Schritte, um Ihre Systemd-Timer-Einheiten zu erstellen und zu verwalten:

  1. Erstellen Sie die Service-Einheitendatei: Definieren Sie Ihre Aufgabe in einer .service-Datei. Platzieren Sie sie in /etc/systemd/system/ (oder ~/.config/systemd/user/ für benutzerspezifische Timer).

    sudo nano /etc/systemd/system/mytask.service
    

    Fügen Sie den obigen Beispiel-Service-Inhalt ein und speichern Sie ihn.

  2. Erstellen Sie die Timer-Einheitendatei: Definieren Sie den Zeitplan in einer entsprechenden .timer-Datei. Platzieren Sie sie im selben Verzeichnis wie die Service-Datei.

    sudo nano /etc/systemd/system/mytask.timer
    

    Fügen Sie den obigen Beispiel-Timer-Inhalt ein und speichern Sie ihn.

  3. Systemd-Daemon neu laden: Nach dem Erstellen oder Ändern von Einheitendateien müssen Sie systemd anweisen, seine Konfiguration neu zu laden.

    sudo systemctl daemon-reload
    
  4. Timer aktivieren: Damit der Timer automatisch beim Booten startet, aktivieren Sie ihn.

    sudo systemctl enable mytask.timer
    

    Hinweis: Sie aktivieren NICHT die Service-Datei, wenn sie ausschließlich vom Timer ausgelöst werden soll.

  5. Timer starten: Starten Sie den Timer sofort. Er wird dann gemäß seinem Zeitplan ausgeführt.

    sudo systemctl start mytask.timer
    

Timer-Einheiten verwalten und überwachen

Systemd bietet mehrere systemctl-Befehle zum Verwalten und Überwachen Ihrer Timer:

  • Alle Timer auflisten: Alle aktiven und inaktiven Timer anzeigen.

    systemctl list-timers
    

    Dieser Befehl liefert eine Ausgabe wie:

    NEXT                        LEFT        LAST        PASSED      UNIT          ACTIVATES
    Tue 2023-10-27 08:00:00 UTC 10h left    Wed 2023-10-26 08:00:00 UTC 14h ago       mytask.timer  mytask.service
    

    Dies zeigt, wann der Timer als nächstes ausgeführt werden soll, wie lange es noch dauert, wann er zuletzt ausgeführt wurde und welchen Dienst er aktiviert.

  • Timer für eine bestimmte Einheit auflisten: Wenn Sie Timer sehen möchten, die sich auf einen bestimmten Dienst beziehen.

    systemctl list-timers --all | grep mytask.service
    
  • Timer-Status prüfen: Detaillierte Informationen zu einem bestimmten Timer erhalten.

    systemctl status mytask.timer
    

    Dies zeigt an, ob der Timer aktiv ist, wann er als nächstes ausgeführt werden soll und die letzten Protokolleinträge.

  • Dienstprotokolle anzeigen: Um die Ausgabe und den Status der vom Timer ausgeführten Aufgabe zu sehen, überprüfen Sie die Protokolle des zugehörigen Dienstes.

    journalctl -u mytask.service
    

    Sie können die Protokolle auch in Echtzeit verfolgen:

    journalctl -f -u mytask.service
    
  • Timer stoppen: Wenn Sie einen Timer vorübergehend deaktivieren müssen.

    sudo systemctl stop mytask.timer
    
  • Timer deaktivieren: Um zu verhindern, dass ein Timer beim Booten startet, und ihn zu stoppen, falls er läuft.

    sudo systemctl disable --now mytask.timer
    

Erweiterte Timer-Konfigurationen

Bestimmte Intervalle festlegen

Anstelle von daily oder hourly können Sie genauere Intervalle definieren:

  • Alle N Minuten: OnUnitActiveSec=15min (wird 15 Minuten nach der letzten Aktivierung des Dienstes ausgeführt).
  • Bestimmte Zeiten: OnCalendar=*-*-* 02:30:00 (wird täglich um 2:30 Uhr ausgeführt).
  • Bedingungen kombinieren: OnCalendar=Mon..Fri *-*-* 08:00:00 (wird an Wochentagen um 8 Uhr ausgeführt).

AccuracySec zum Stromsparen verwenden

Wenn Ihre Aufgabe nicht zu einem genauen Zeitpunkt ausgeführt werden muss, sollten Sie AccuracySec verwenden. Zum Beispiel teilt AccuracySec=5min systemd mit, dass es in Ordnung ist, das System innerhalb von 5 Minuten nach der geplanten Zeit aufzuwecken. Dies ermöglicht es systemd, Timer-Ereignisse zu bündeln und das System möglicherweise länger in einem niedrigeren Energiezustand zu halten.

[Timer]
OnCalendar=hourly
AccuracySec=5min

Persistent vs. WakeSystem

  • Persistent=true stellt sicher, dass, wenn ein OnCalendar-Ereignis aufgrund eines ausgeschalteten Systems verpasst wird, es beim nächsten Booten einmal ausgeführt wird. Dies ist entscheidend für Aufgaben, die nicht übersprungen werden dürfen.
  • WakeSystem=true fordert systemd auf, das System aus dem Ruhezustand für den Timer aufzuwecken, wenn das System und die Hardware dies unterstützen. Es ist nicht dasselbe wie die Entscheidung, ob die Maschine mit Netzstrom oder Batterie betrieben wird.

Timer vs. Cron

Funktion Systemd-Timer Cron
Integration Tiefe Integration mit systemd-Diensten, Targets Eigenständiges Dienstprogramm
Planung Flexibel (Kalender, relativ, bootbasiert) Hauptsächlich zeitbasierte Ausdrücke
Protokollierung Zentralisiert über journalctl Verstreut (/var/log/syslog, /var/log/cron.log)
Fehlerbehandlung Kann Aktionen an Dienstfehler binden Grundlegende E-Mail-Benachrichtigungen
Abhängigkeiten Kann von anderen aktiven Diensten abhängen Eingeschränkt
Ausführung Kann als bestimmte Benutzer, Gruppen ausgeführt werden Kann über Crontab als bestimmte Benutzer ausgeführt werden
Energiemanagement Kann für Stromsparen optimiert werden (AccuracySec) Weniger direkte Kontrolle

Wann Sie Systemd-Timer wählen sollten:

  • Wenn Sie eine engere Integration mit anderen systemd-Diensten benötigen.
  • Wenn zentralisierte Protokollierung und einfachere Fehlersuche Priorität haben.
  • Wenn Sie erweiterte Planungsoptionen benötigen (z. B. Zeit seit letzter Ausführung).
  • Für Aufgaben im Zusammenhang mit dem Systemzustand oder Energiemanagement.

Wann Cron möglicherweise noch bevorzugt wird:

  • Für sehr einfache, eigenständige Aufgaben auf Systemen, die systemd nicht vollständig nutzen.
  • Für maximale Kompatibilität zwischen verschiedenen Linux-Distributionen und älteren Systemen.

Behebung häufiger Probleme

  • Aufgabe wird nicht ausgeführt:
    • Timer-Status prüfen: systemctl status mytask.timer. Achten Sie auf Active: active und Triggered...-Meldungen.
    • Dienstprotokolle prüfen: journalctl -u mytask.service. Stellen Sie sicher, dass das Skript ausführbar ist und keine Fehler enthält.
    • OnCalendar-Syntax überprüfen: Verwenden Sie systemd-analyze calendar 'your-calendar-string' zum Testen.
    • Stellen Sie sicher, dass der Timer aktiviert und gestartet ist: systemctl list-timers --all.
  • Aufgabe läuft zu früh/zu spät:
    • Überprüfen Sie AccuracySec und RandomizedDelaySec.
    • Stellen Sie sicher, dass die Systemuhr genau ist (timedatectl status).
  • Berechtigungsfehler:
    • Bestätigen Sie, dass der in der .service-Datei angegebene User und die Group die erforderlichen Berechtigungen für das Skript und alle Dateien haben, auf die es zugreift.
    • Wenn kein Benutzer angegeben ist, wird standardmäßig root verwendet. Seien Sie vorsichtig mit Root-Rechten.

Fazit

Verwenden Sie einen Systemd-Timer, wenn die Aufgabe zur Dienstebene der Maschine gehört: Backups, Bereinigungsaufgaben, Überwachungsprüfungen, Zertifikatserneuerungs-Hooks und andere betriebliche Arbeiten. Erstellen Sie zuerst den Dienst, dann den Timer, führen Sie systemctl daemon-reload aus, aktivieren und starten Sie den Timer, und überprüfen Sie ihn dann mit systemctl list-timers --all und journalctl -u your.service.