Dienste steuern
systemctl ist der Befehl, mit dem du mit systemd sprichst. Ein Dutzend Unterbefehle deckt den Alltag ab. Auf dieser Seite probierst du sie an SSH und an einem frisch installierten Webserver aus und schreibst dann einen eigenen Dienst.
Die wichtigsten Unterbefehle
Abschnitt betitelt „Die wichtigsten Unterbefehle“| Befehl | Wirkung |
|---|---|
systemctl status NAME |
Zustand, PID, Speicherverbrauch und die letzten Logzeilen |
sudo systemctl start NAME |
Jetzt starten |
sudo systemctl stop NAME |
Jetzt stoppen |
sudo systemctl restart NAME |
Stoppen und neu starten (Prozess wird beendet) |
sudo systemctl reload NAME |
Konfiguration neu einlesen, ohne den Prozess zu beenden (nicht jeder Dienst kann das) |
sudo systemctl enable NAME |
Beim Booten automatisch starten |
sudo systemctl disable NAME |
Nicht mehr automatisch starten |
systemctl is-active NAME |
Nur active oder inactive, ideal für Skripte |
systemctl is-enabled NAME |
Nur enabled oder disabled |
Das .service am Ende darfst du weglassen, systemctl status ssh und systemctl status ssh.service sind dasselbe. Lesende Befehle gehen ohne sudo, verändernde brauchen es.
Hands-on: mit SSH, dem Dienst, über den du gerade verbunden bist.
systemctl status sshsystemctl is-active sshsystemctl is-enabled sshLies die Status-Ausgabe Zeile für Zeile: Loaded nennt die Unit-Datei und ob sie enabled ist, Active den Zustand und seit wann, Main PID den Prozess, darunter die letzten Logzeilen. Was passiert wohl, wenn du sudo systemctl stop ssh tippst, während du per SSH verbunden bist? Bestehende Verbindungen bleiben offen, aber neue sind nicht mehr möglich. Lass es besser bleiben.
enable ist nicht start
Abschnitt betitelt „enable ist nicht start“Das ist die häufigste Verwechslung. start und stop wirken jetzt, enable und disable wirken beim nächsten Boot. Die beiden Achsen sind unabhängig:
flowchart LR
subgraph jetzt["Jetzt"]
direction TB
start["systemctl start"] --> laeuft["läuft"]
stop["systemctl stop"] --> steht["gestoppt"]
end
subgraph boot["Nach dem nächsten Boot"]
direction TB
enable["systemctl enable"] --> auto["startet automatisch"]
disable["systemctl disable"] --> nicht["startet nicht"]
end
enabled |
disabled |
|
|---|---|---|
| active | Normalfall für einen Serverdienst | Läuft nur bis zum nächsten Reboot |
| inactive | Gestoppt, kommt nach dem Reboot wieder | Aus, und bleibt aus |
enable erzeugt lediglich einen Symlink in /etc/systemd/system/multi-user.target.wants/, disable entfernt ihn. Wer beides auf einmal will, nimmt sudo systemctl enable --now NAME beziehungsweise disable --now.
Hands-on: nginx installieren
Abschnitt betitelt „Hands-on: nginx installieren“sudo apt updatesudo apt install -y nginxsystemctl status nginxcurl localhostcurl holt die Startseite des Webservers, du solltest HTML mit «Welcome to nginx!» sehen. Ubuntu-Pakete aktivieren und starten ihren Dienst bei der Installation gleich mit. Jetzt der Zyklus:
sudo systemctl stop nginxcurl localhostsudo systemctl start nginxcurl -s localhost | head -n 4sudo systemctl disable nginxsystemctl is-enabled nginxsudo systemctl enable nginxBei gestopptem nginx meldet curl «Connection refused». Was zeigt ls -l /etc/systemd/system/multi-user.target.wants/ nach disable und nach enable?
Und der Unterschied zwischen restart und reload:
systemctl show nginx -p MainPIDsudo systemctl reload nginxsystemctl show nginx -p MainPIDsudo systemctl restart nginxsystemctl show nginx -p MainPIDNach reload ist die PID gleich geblieben, nach restart ist es ein neuer Prozess. Für Konfigurationsänderungen ist reload darum der bessere Weg, falls der Dienst ihn anbietet.
Aufbau einer Unit-Datei
Abschnitt betitelt „Aufbau einer Unit-Datei“systemctl cat nginxsystemctl cat zeigt die Unit-Datei mit ihrem Pfad. Das Format ist das klassische INI-Format mit drei Abschnitten:
[Unit]Description=A high performance web server and a reverse proxy serverAfter=network.target
[Service]Type=forkingExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reloadExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pidTimeoutStopSec=5KillMode=mixed
[Install]WantedBy=multi-user.target| Abschnitt | Schlüssel | Bedeutung |
|---|---|---|
[Unit] |
Description= |
Text, der in status erscheint |
After= |
Erst starten, wenn diese Unit gestartet ist (Reihenfolge, keine harte Abhängigkeit) | |
[Service] |
Type= |
simple (Standard, Prozess bleibt im Vordergrund), forking (Dienst legt sich selbst in den Hintergrund), oneshot (läuft einmal durch, dann fertig) |
ExecStart= |
Der Befehl, absoluter Pfad zwingend | |
ExecReload= |
Was systemctl reload ausführt |
|
Restart= |
no, on-failure oder always: automatisch neu starten? |
|
User= |
Als welcher Benutzer der Dienst läuft (Standard: root) | |
[Install] |
WantedBy= |
In welches Target enable den Link legt |
Die vollständige Liste steht in man systemd.service und man systemd.unit, die Manpages sind lang, aber gut.
Hands-on: ein eigener Dienst
Abschnitt betitelt „Hands-on: ein eigener Dienst“Ein Dienst, der alle 10 Sekunden eine Zeile mit Datum in eine Datei schreibt. Nutzlos, aber vollständig, und die Vorlage für alles Spätere.
- Das Skript. Es endet nie, genau wie ein echter Dienst:
Anlegen mit
/usr/local/bin/ticker.sh #!/usr/bin/env bash# ticker.sh: schreibt alle 10 Sekunden eine Zeile mit Zeitstempelset -euo pipefaillogfile="/var/tmp/ticker.log"while true; doecho "$(date '+%F %T') tick" >> "$logfile"sleep 10donesudo vim /usr/local/bin/ticker.sh, dann ausführbar machen und einmal von Hand testen:Nach ein paar Sekunden mit Ctrl+C abbrechen undTerminal-Fenster sudo chmod 755 /usr/local/bin/ticker.sh/usr/local/bin/ticker.shcat /var/tmp/ticker.logansehen. Erst wenn das Skript von Hand läuft, lohnt sich der Dienst. - Die Unit-Datei:
/etc/systemd/system/ticker.service [Unit]Description=Ticker: schreibt alle 10 Sekunden eine Zeile nach /var/tmp/ticker.log[Service]Type=simpleExecStart=/usr/local/bin/ticker.shRestart=on-failureRestartSec=1[Install]WantedBy=multi-user.target - systemd kennt neue Dateien erst nach einem
daemon-reload. Das brauchst du nach jeder Änderung an einer Unit-Datei:Terminal-Fenster sudo systemctl daemon-reloadsudo systemctl start tickersystemctl status ticker - Prüfen, ob er arbeitet, und dann für den Boot aktivieren:
Terminal-Fenster tail -f /var/tmp/ticker.logsudo systemctl enable tickerjournalctl -u tickertail -fbeendest du mit Ctrl+C. Im Journal stehen bisher nur «Started» und «Stopped», weil das Skript selbst nichts auf die Standardausgabe schreibt. Alles, was ein Dienst auf stdout oder stderr ausgibt, landet automatisch im Journal, darum brauchen Dienste oft gar keine eigene Logdatei.
Lösung anzeigen
script labs/linux/09-dienste/dienste.txtsystemctl status tickersystemctl is-active tickersystemctl is-enabled tickertail -n 5 /var/tmp/ticker.logsudo systemctl stop tickersystemctl status tickersudo systemctl start ticker# Antwort 1: Nach dem Reboot läuft er nicht, weil kein Link in multi-user.target.wants existiert.sudo kill -9 "$(systemctl show ticker -p MainPID --value)"sleep 6systemctl status ticker# Antwort 2: Der Prozess stirbt, systemd meldet "failed" und startet ihn wegen Restart=on-failure nach einer Sekunde mit neuer PID.exitcp /etc/systemd/system/ticker.service /usr/local/bin/ticker.sh labs/linux/09-dienste/Selbstcheck · 5 Fragen
Weiterführend
Abschnitt betitelt „Weiterführend“man systemd.service,man systemd.unit- systemd.io und die Manpages von freedesktop.org