Systemd Unit-Files

Siehe auch

„Units“ (letztlich Konfigurationsdateien auf .ini-Art) gibt es u.a. für das Starten von Server-Diensten, Mounten von Datenträgern oder zum Starten von Service Units, wenn Anfragen auf einem bestimmten Netzwerk-Port eingehen.

Systemd „Service Unit“ Konfigurationsdateien

Eine Unit-Konfigurationsdatei mit Dateiendung .service ist nichts anderes als eine Ini-Datei und enthält Informationen zu einem Prozess, der von Systemd kontrolliert (Start/Stop/Status) und überwacht wird.

Minimales Beispiel:

/etc/systemd/system/myservice.service
[Unit]
Description=MyService

[Service]
ExecStart=/opt/myservice/start

[Install]
WantedBy=multi-user.target

Bemerkung

  • Prozentzeichen (%) müssen durch ein vorangestelltes %-Zeichen maskiert werden (Quoting).

  • Subshells lassen sich mittels ExecStart=/usr/bin/env bash -c 'mycmd --myparam $(mysubcmd)' ausführen.

Wird eine .service-Datei erzeugt oder geändert, muss Systemd das mitbekommen:

systemctl daemon-reload

Installation, Start/Stop/Status usw. dann mittels:

systemctl enable myservice
systemctl start myservice
systemctl restart myservice

systemctl status myservice

systemctl stop myservice
systemctl disable myservice

Wichtig: das Abschalten eines Dienstes liefert nur eine Ausgabe, wenn der Dienst vorhanden und aktiviert war. In allen anderen Fällen wird keine Ausgabe erzeugt, auch nicht, wenn der Dienst gar nicht existiert.

Unit File Cheat Sheet

Eine Auswahl:

[Unit]

Description=My Service Description

# Link zu Doku kann mehrfach angegeben werden
Documentation=man:myserviced(8) man:mycreate(8)
Documentation=http://.../myservice.html

# Unbedingt benötigte Units, z.B. ein Socket
# Werden falls nötig ebenfalls gestartet.
# Wird einer der Required Services gestoppt, wird auch unser Dienst gestoppt.
Requires=syslog.socket

# Schwächer als Requires. Unser Dienst wird auch hier erst
# gestartet, wenn die angegebenen Units
# gestartet wurden, aber eben auch wenn diese failen.
Wants=network.target

# Starte unseren Dienst vor den hier angegebenen
# Targets und Diensten:
Before=network.target network.service

# Starte unseren Dienst erst nach folgenden Targets
# und/oder Diensten.
# Default: basic.target
After=syslog.target network.target mongodb.service
After=rc-local.service

# Wen mag unser Dienst gar nicht? Falls diese Dienste gestartet werden, stoppe unseren.
Conflicts=ntpd.service sendmail.service exim.service

# Starte Dienst nur, wenn folgende Bedingungen
# zutreffen (Verneinung mit "!"):

# selbsterklärendes
ConditionDirectoryNotEmpty=/var/crash
ConditionKernelCommandLine=!audit=0
ConditionPathExists=!/run/systemd/readahead/noreplay
ConditionPathExists=/.readahead

# Prüfe, ob das System in einer virtuellen Umgebung
#   läuft.
# Allgemeine Werte: yes/no/true/false, vm, container
# Spezifische Werte: qemu, kvm, zvm, vmware,
#   microsoft, oracle, xen, bochs, uml, openvz, lxc,
#   lxc-libvirt, systemd-nspawn, docker
ConditionVirtualization=false

# selbsterklärend
RefuseManualStop=yes


[Service]

# Werte: simple, forking, oneshot, dbus, notify,
    idle
# Default: simple, wenn Type nicht und
#   ExecStart angegeben wurde
# simple: ExecStart ist der Hauptprozess. Muss der
#   Prozess mit anderen kommunizieren, sollten seine
#   Kommunikationskanäle vorher per Systemd
#   gestartet werden. Nachfolgende Dienste werden
#   gestartet, sobald unser Prozess angetriggert
#   wurde.
#   RemainAfterExit ist hier hilfreich.
# forking: für traditionelle UNIX-Daemons, die über
#   einen Hauptprozess Kind-Prozesse starten und
#   sich danach beenden. Sollte mit PIDFILE= für
#   den Hauptprozess eingesetzt werden. Nachfolgende
#   Prozesse werden gestartet, sobald sich der
#   Hauptprozess beendet.
# oneshot: wie simple, darf aber mehr als eine
#   ExecStart-Anweisung haben. Nachfolgende Dienste
#   müssen warten, bis unser Prozess ganz gestartet
#   wurde. Wird nur einmal ausgeführt, falls mehrere
#   Dienste uns als Abhängigkeit angegeben haben.
#   RemainAfterExit ist hier hilfreich.
Type=oneshot

# Bei "yes" sieht Systemd den Dienst als aktiv an,
#   sobald ExecStart erfolgreich war, und auch,
#   wenn alle unsere Prozesse beendet wurden.
#   Hat Auswirkungen auf automatische Neustarts
#   von abgestürzten Diensten.
# Werte: yes/no/true/false
# Default: no
RemainAfterExit=no

# Umgebungsvariablen setzen
Environment="VAR1=word1 word2" VAR2=word3

# Umgebungseinstellungen aus Datei auslesen. Mit "-"
# vorneweg ignorieren, wenn es sie nicht gibt.
EnvironmentFile=-/etc/sysconfig/myservice

# Start- und Stop-Anweisung
# Wird ExecStop nicht angegeben, wird Systemd beim
# Beenden allen Prozessen, die durch unseren
# Dienst gestartet wurden, ein SIGTERM-Signal
# senden (kill -15); nach einem Timeout folgt ein
# SIGKILL-Signal (kill -9).
# Möchte man den Exit-Status des Exec-Kommandos
# ignorieren, stellt man diesem ein Minus-Zeichen
# voran.
ExecStartPre=/usr/bin/rm -f /var/run/myservice.pid
ExecStart=/usr/bin/bash -c "/opt/myservice/start" $MYSERVICEARGS
ExecStartPost=-/sbin/auditctl -R /etc/audit/audit.rules
ExecStop=-/usr/bin/bash -c "/opt/myservice/stop"
ExecReload=/usr/bin/kill -HUP $MAINPID

# Absoluter Pfad zur PID-Datei; benötigt bei
# Type=forking. Systemd liest hier die PID des
# Hauptprozesses aus.
PIDFile=/var/run/myservice.pid

# temp-Dateien liegen in einem sicheren Verzeichnis,
# nicht im /tmp
PrivateTmp=true

# Zeit für Startup/Shutdown, nur Shutdown geben
TimeoutSec=300
TimeoutStopSec=300

# Automatischer Restart unseres Dienstes bei
# Exit, Kill oder Timeout; ausser natürlich
# bei "systemctl stop" oder "... restart".
# Werte: no, on-success, on-failure, on-abnormal,
#   on-watchdog, on-abort, always
# Default: no
Restart=on-failure

# Warte die angegebene Zeit mit dem Restart
# Default: 100ms
RestartSec=5min 20s

# Unter anderem Benutzer laufen lassen
User=%i
Group=mygroup


[Install]

# Wird nur bei "systemctl enable" und "... disable"
# ausgelesen.

# In welches Target wird unser Dienst platziert?
# In den allermeisten Fällen "multi-user.target";
# andere Werte als Beispiel: basic.target,
#   default.target, getty.target, sysinit.target,
#   system-update.target
WantedBy=multi-user.target

# Installiere den Dienst nur, wenn ...
# wie weiter oben. Beispiel:
ConditionKernelCommandLine=!audit=0
# ...

# Zusätzliche Namen für unseren Service
Alias=yourservice.service

# Zusätzlich zu (de-)installierende Units, wenn
#   unser Dienst (de-)installiert wird
Also=NetworkManager-dispatcher.service

Built on 2024-04-18