2.5 »systemd«
Nach dem Bootvorgang, in dem der Kernel das root-Filesystem eingebunden und alle notwendigen Module geladen hat, übernimmt der systemd-Daemon den weiteren Ablauf.
Der klassische init-Prozess folgt dem in System V[ 3 ] vorgestellten Verfahren und wird nach diesem auch SysVinit genannt. Er ist verantwortlich für das Starten der Dienste in der richtigen Reihenfolge, das Folgen und auch den Wechsel von Runleveln sowie für das Stoppen von Prozessen. Dieses Verfahren ist sehr robust, aber leider auch sehr statisch.
systemd ist der Nachfolger, den mittlerweile alle Distributionen verwenden. Mit systemd gibt es einen Übergang vom statischen Starten von Skripten zum eventbasierten Starten. So können Bedingungen definiert werden, die erfüllt sein müssen, um Dienste starten zu können (beispielsweise wird der Webserver erst dann gestartet, wenn das Netzwerk verfügbar ist, oder ein Virenscanner erst dann, wenn ein USB-Stick eingesteckt wird). Der Start von Diensten mit systemd ist im Unterschied zu SysVinit hoch parallelisierbar. Als besonderes Feature ist systemd auch in der Lage, abgestürzte Dienste neu zu starten.
Es gibt kaum ein Thema in den letzten Jahren, das in der Linux-Community so kontrovers diskutiert wurde wie die Einführung von systemd.
systemd schickt sich an, den kompletten altbekannten und bewährten Bootvorgang auf den Kopf zu stellen. Den einen gehen die Änderungen zu weit, die anderen feiern mit systemd die Ankunft im neuen Jahrtausend. Tatsache ist, dass mit systemd Start-Skripte – genauer gesagt Startkonfigurationen – parallel ausgeführt werden können und nicht wie früher linear. Dazu kommt, dass systemd Programme voneinander kapselt und in eigenen Control Groups und Namespaces startet und so sicherstellt, dass beim Beenden eines Dienstes auch alle Prozesse im gleichen Namespace mit beendet werden und dass es keine verwaisten Prozesse gibt.
Weitergehende Änderungen sind, dass mit journald ein eigenes Logging-Framework mitgeliefert wird, das es erlaubt, fälschungssichere Logs zu führen. Dadurch soll das altbekannte syslog abgelöst werden. timers in systemd sind in der Lage, klassische Cron- und Anacron-Jobs abzulösen, systemd-mounts könnten die fstab überflüssig machen.
Die beiden Hauptkritikpunkte der systemd-Gegner sind, dass systemd von der UNIX-Philosophie »one task, one tool« abweicht und dass das systemd-Team bei der Weiterentwicklung zum Teil fragwürdige Entscheidungen trifft.
2.5.1 Begrifflichkeiten
systemd wird mit Units verwaltet. Units kapseln verschiedene Aspekte eines Systems und können untereinander in Beziehung gesetzt werden. Die Definitionen der Units sind einfache Textdateien, die ein wenig an ini-Dateien aus Windows erinnern. Die einzelnen UnitTypen sind die folgenden:
-
Service Units
werden benutzt, um Dienste und Prozesse zu starten. -
Socket Units
kapseln IPC- oder Netzwerk-Sockets, die vor allem gebraucht werden, um Socket-basierend Dienste zu aktivieren. -
Target Units
können zur Gruppierung von Diensten oder zur Erstellung von Synchronisationspunkten benutzt werden (hiermit lassen sich Runlevel wie im SysVinit emulieren). -
Device Units
sind die Verbindung zu Kernel-Devices und können ebenfalls benutzt werden, um Device-basierende Dienste zu steuern. -
Mount Units
kontrollieren Mountpunkte im System. -
Automount Units
werden für zugriffsbasiertes Einbinden von Dateisystemen benutzt und dienen insbesondere auch der Parallelisierung im Bootprozess. -
Snapshot Units
können den Status einer Anzahl von systemd-Units aufzeichnen und diesen Status durch Aktivierung auch wiederherstellen. -
Timer Units
bieten die Möglichkeit, eine zeitbasierte Steuerung anderer Units vorzunehmen. -
Swap Units
verwalten – analog zu Mount Units – Swap-Speicherplatz. -
Path Units
werden benutzt, um andere Dienste bei einer Veränderung von Dateisystemobjekten zu aktivieren. -
Slice Units
gruppieren Units in hierarchischer Form, die Systemprozesse – beispielsweise Service oder Scope Units – verwalten. -
Scope Units
gleichen Service Units, verwalten aber Fremdprozesse, anstatt sie nur zu starten.
Wie Sie allein an den verschiedenartigen Units feststellen können, kann man in systemd vielfältige Aspekte eines Systems beeinflussen. Im Folgenden gehen wir auf System Units ein, das sind die Units, mit denen Sie am häufigsten in Kontakt kommen werden.
2.5.2 Kontrollieren von Diensten
Das Hauptkommando, mit dem Sie systemd kontrollieren können, heißt systemctl. Dieser Befehl wird auch benutzt, um Dienste zu verwalten. Analog zu den früheren init-Skripten gibt es die Kommandos start, stop, reload, restart und status.
[+] systemctl macht Gebrauch von Farben im Terminal. Stellen Sie daher bitte sicher, dass Ihr Terminal auch Farben darstellen kann.
Service Units in systemd enden auf .service, diese Endung muss aber nicht explizit angegeben werden. In Listing 2.17 sehen Sie, dass weder das Stopp- noch das Start-Subkommando sehr gesprächig ist, daher sollte das Ergebnis mit einer Statusabfrage überprüft werden.
# systemctl stop sshd
# systemctl status sshd
* sshd.service - OpenSSH server daemon
Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: \
enabled)
Active: inactive (dead) since Fre 2018-08-05 13:26:32 CEST; 5s ago
Docs: man:sshd(8)
man:sshd_config(5)
Process: 2054 ExecStart=/usr/sbin/sshd -D $OPTIONS (code=exited, status=0/SUCCESS)
Main PID: 2054 (code=exited, status=0/SUCCESS)
Aug 05 13:25:49 centos sshd[2054]: Server listening on 0.0.0.0 port 22.
Aug 05 13:25:49 centos sshd[2054]: Server listening on :: port 22.
Aug 05 13:25:49 centos systemd[1]: Started OpenSSH server daemon.
Aug 05 13:25:49 centos systemd[1]: Starting OpenSSH server daemon...
Aug 05 13:26:32 centos sshd[2054]: Received signal 15; terminating.
Aug 05 13:26:32 centos systemd[1]: Stopping OpenSSH server daemon...
Aug 05 13:26:32 centos systemd[1]: Stopped OpenSSH server daemon.
# systemctl start sshd
# systemctl status sshd
* sshd.service - OpenSSH server daemon
Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: \
enabled)
Active: active (running) since Fre 2018-08-05 13:26:43 CEST; 5s ago
Docs: man:sshd(8)
man:sshd_config(5)
Main PID: 2072 (sshd)
CGroup: /system.slice/sshd.service
`-2072 /usr/sbin/sshd -D
Aug 05 13:26:43 centos sshd[2072]: Server listening on 0.0.0.0 port 22.
Aug 05 13:26:43 centos sshd[2072]: Server listening on :: port 22.
Aug 05 13:26:43 centos systemd[1]: Started OpenSSH server daemon.
Aug 05 13:26:43 centos systemd[1]: Starting OpenSSH server daemon...
Listing 2.17 Stoppen des SSH-Servers
Gerade die Statusausgaben sind auf den ersten Blick sehr verwirrend:
-
In der ersten Zeile finden Sie den Namen des Dienstes und die Beschreibung.
-
Die Zeile, die mit Loaded: beginnt, zeigt Ihnen, ob die Unit-Datei geladen ist, und den Speicherort. Mit enabled ist gemeint, dass die Unit standardmäßig (beispielsweise beim Start des Systems) ausgeführt wird und wie die Einstellung des Distributors (CentOS, Debian, openSUSE oder Ubuntu) ist. Mehr Informationen dazu finden Sie in Abschnitt 2.5.3, »Aktivieren und Deaktivieren von Diensten«.
-
Active: kennzeichnet den aktuellen Status und seit wann dieser Status besteht.
-
Docs: verweist auf Dokumentationen zum Service, hier sind es Manpages, üblich ist aber auch der Hinweis auf eine URL.
-
Process: zeigt Ihnen, wie der Dienst gestartet wurde, und den letzten Status.
-
Main PID: enthält die Hauptprozess-ID.
-
CGroup: stellt die Control Group, in der der Dienst gestartet wurde dar.
-
Zum Schluss folgt ein Auszug der letzten Log-Ausgaben. Wie Sie mehr Log-Ausgaben sehen können, erfahren Sie in Abschnitt 2.5.8.
Die Subkommandos restart, um den Dienst neu zu starten, und reload, um die Konfiguration – in diesem Fall /etc/ssh/sshd_config – neu einzulesen, vervollständigen die Basiskommandos.
Folgende Befehle wurden in diesem Abschnitt behandelt:
-
systemctl start <SERVICE>
-
systemctl stop <SERVICE>
-
systemctl status <SERVICE>
-
systemctl restart <SERVICE>
-
systemctl reload <SERVICE>
2.5.3 Aktivieren und Deaktivieren von Diensten
Units werden mit den Subkommandos enable und disable aktiviert und deaktiviert:
# systemctl disable sshd
Removed symlink /etc/systemd/system/multi-user.target.wants/sshd.service.
# systemctl enable sshd
Created symlink from /etc/systemd/system/multi-user.target.wants/sshd.service \
to /usr/lib/systemd/system/sshd.service.
Listing 2.18 Aktivieren und Deaktivieren des SSH-Servers
Die Subkommandos lesen die Servicedefinition und schauen, für welches Target der Dienst aktiviert werden soll. In Listing 2.18 sehen Sie, dass es das multi-user.target für den Dienst sshd ist. Beim Aktivieren wird nun ein Link in dem Verzeichnis des Targets erstellt und beim Deaktivieren wieder gelöscht.
Folgende Befehle wurden in diesem Abschnitt behandelt:
-
systemctl enable <SERVICE>
-
systemctl disable <SERVICE>
2.5.4 Erstellen und Aktivieren eigener Service Units
Wie Sie bereits in Listing 2.17 im Abschnitt 2.5.2 gesehen haben, ist die Konfigurationsdatei /usr/lib/systemd/system/sshd.service die Datei, in der die Angaben des SSH-Servers gespeichert werden. Den Inhalt sehen Sie im folgenden Listing. Viele Ausgaben des Statuskommandos werden durch Einträge im Servicefile angezeigt, beispielsweise die Description oder Documentation:
# cat /usr/lib/systemd/system/sshd.service
[Unit]
Description=OpenSSH server daemon
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target sshd-keygen.service
Wants=sshd-keygen.service
[Service]
EnvironmentFile=/etc/sysconfig/sshd
ExecStart=/usr/sbin/sshd -D $OPTIONS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s
[Install]
WantedBy=multi-user.target
Listing 2.19 Inhalt von »sshd.service«
Die Ausgabe von systemctl show sshd zeigt Ihnen neben den Einträgen aus dem Servicefile auch noch die ganzen Standardoptionen und Statusinformationen an. Die 143 Zeilen Information werden Ihnen an dieser Stelle erspart, da Sie diese jederzeit selbst abrufen können. Die einzelnen Parameter der Konfiguration aus Listing 2.19 haben die folgende Bedeutung:
-
Description
enthält eine lesbare Beschreibung des Dienstes. -
Documentation
verweist auf weiterführende Informationen. -
After
wird benutzt, um Abhängigkeiten zu definieren. In diesem Fall soll der Dienst nach den angegebenen anderen Diensten gestartet werden (analog dazu gibt es Before). -
Wants
erfordert, dass die angegebenen Dienste vor dem Start erfolgreich gelaufen sind (abgemilderte Form von Require). -
EnvironmentFile
gibt eine Datei mit Umgebungsvariablen an, die zur Verfügung stehen sollen. -
ExecStart
enthält das Kommando, das zum Start benutzt wird (analog dazu gibt es ExecStop). -
ExecReload
Mit diesem Kommando werden die Konfigurationsdateien neu eingelesen. -
KillMode
zeigt, mit welchem Verfahren der Prozess gekillt werden kann. -
Restart
definiert die Option für den automatischen Neustart des Dienstes. -
RestartSec
enthält die Zeit, nach der neu gestartet werden soll. -
WantedBy
beschreibt das Target (oder den Service), durch das der Dienst automatisch gestartet werden soll.
Zusätzlich zu den Optionen, die Sie in der Definition des SSH-Servers sehen, gibt es noch die folgenden Optionen, denen Sie häufiger begegnen werden:
-
Before
wird analog zu After benutzt, um Abhängigkeiten zu definieren. In diesem Fall soll der Dienst vor den angegebenen anderen Diensten gestartet werden. -
Require
erfordert, dass die angegebenen Dienste vor dem Start erfolgreich gelaufen sind. Wenn die Dienste beendet werden, soll unser Dienst ebenfalls gestoppt werden. -
ExecStop
enthält das Kommando, das zum Stoppen benutzt wird. -
Conflicts
beendet die angegebenen Dienste, wenn dieser jetzt konfigurierte Dienst gestartet wird. -
OnFailure
enthält eine Liste an Units, die gestartet werden, wenn sich dieser Service fehlerhaft beendet. -
Type
ist für Services entweder simple oder forking, wobei das Erste für einen Prozess steht, der ständig läuft, und das Zweite für einen Prozess, der einen Kindprozess abspaltet und sich danach beendet. (oneshot ist ein Service, der nur läuft und sich danach selbst beendet. Dieser Typ wird manchmal als Ziel für OnFailure benutzt.)
[+] Eigene Servicedateien sollten Sie im dafür vorgesehenen Verzeichnis /etc/systemd/system anlegen und nach dem Anlegen mittels systemctl daemon-reload aktivieren.
Weitergehende Informationen finden Sie in der Manpage systemd.unit.
Folgender Befehl wurde im aktuellen Abschnitt behandelt:
-
systemctl show <SERVICE>
2.5.5 Target Units
Die folgenden Targets finden sich auf einem Desktop-System:
# systemctl list-units "*.target"
UNIT LOAD ACTIVE SUB DESCRIPTION
basic.target loaded active active Basic System
bluetooth.target loaded active active Bluetooth
cryptsetup.target loaded active active Encrypted Volumes
getty.target loaded active active Login Prompts
graphical.target loaded active active Graphical Interface
local-fs-pre.target loaded active active Local File Systems (Pre)
local-fs.target loaded active active Local File Systems
multi-user.target loaded active active Multi-User System
network-online.target loaded active active Network is Online
network.target loaded active active Network
nfs-client.target loaded active active NFS client services
paths.target loaded active active Paths
remote-fs-pre.target loaded active active Remote File Systems (Pre)
remote-fs.target loaded active active Remote File Systems
slices.target loaded active active Slices
sockets.target loaded active active Sockets
sound.target loaded active active Sound Card
swap.target loaded active active Swap
sysinit.target loaded active active System Initialization
timers.target loaded active active Timers
LOAD = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB = The low-level unit activation state, values depend on unit type.
20 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.
Listing 2.20 Targets auf einem Desktop-System
Mittels systemctl list-dependencies multi-user.target können Sie sich anzeigen lassen, von welchen Diensten das Multi-User-Target abhängt.
Folgender Befehl wurde in diesem Abschnitt behandelt:
-
systemctl list-units '*.targets'
2.5.6 »systemd«- und Servicekonfigurationen
Ein installiertes System kommt mit einer großen Anzahl an Diensten daher. Um da nicht den Überblick zu verlieren, bietet systemd einige Kommandos, um das laufende System abzufragen. Listing 2.21 zeigt Ihnen einen Auszug der 228 bekannten Units auf einem minimal installierten CentOS-System:
UNIT FILE STATE
[…]
crond.service enabled
fstrim.service static
kdump.service enabled
NetworkManager.service enabled
postfix.service enabled
sshd.service enabled
ctrl-alt-del.target disabled
graphical.target static
hibernate.target static
hybrid-sleep.target static
network-online.target static
runlevel0.target disabled
runlevel1.target disabled
runlevel2.target static
runlevel3.target static
runlevel4.target static
runlevel5.target static
runlevel6.target disabled
[…]
228 unit files listed.
Listing 2.21 Auszug der bekannten Units eines Systems
Von diesen 228 bekannten Units wurden aber nur 96 geladen:
# systemctl list-units
UNIT LOAD ACTIVE SUB DESCRIPTION
[…]
-.mount loaded active mounted /
boot.mount loaded active mounted /boot
dbus.service loaded active running D-Bus System Message Bus
getty@tty1.service loaded active running Getty on tty1
NetworkManager.service loaded active running Network Manager
getty.target loaded active active Login Prompts
local-fs.target loaded active active Local File Systems
multi-user.target loaded active active Multi-User System
network-online.target loaded active active Network is Online
network.target loaded active active Network
systemd-tmpfiles-clean.timer loaded active waiting Daily Cleanup of \
Temporary Directories
[…]
LOAD = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB = The low-level unit activation state, values depend on unit type.
96 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.
Listing 2.22 Auszug der geladenen Unit-Dateien
Folgender Befehl wurde in diesem Abschnitt behandelt:
-
systemctl list-unitfiles
2.5.7 Anzeige von Dienstabhängigkeiten
Wenn man sich die Voraussetzungen anschauen möchte, die erforderlich sind, um eine Unit starten zu können, kann man das Subkommando list-dependencies benutzen:
# systemctl list-dependencies sshd.service
sshd.service
* |-sshd-keygen.service
* |-system.slice
* `-basic.target
* |-microcode.service
* |-rhel-autorelabel-mark.service
* |-rhel-autorelabel.service
* |-rhel-configure.service
* |-rhel-dmesg.service
* |-rhel-loadmodules.service
* |-paths.target
* |-slices.target
* | |--.slice
* | `-system.slice
* |-sockets.target
* | |-dbus.socket
* | |-dm-event.socket
* | |-systemd-initctl.socket
* | |-systemd-journald.socket
* | |-systemd-shutdownd.socket
* | |-systemd-udevd-control.socket
* | `-systemd-udevd-kernel.socket
* |-sysinit.target
* | |-dev-hugepages.mount
* | |-dev-mqueue.mount
* | |-kmod-static-nodes.service
* | |-lvm2-lvmetad.socket
* | |-lvm2-lvmpolld.socket
* | |-lvm2-monitor.service
* | |-plymouth-read-write.service
* | |-plymouth-start.service
* | |-proc-sys-fs-binfmt_misc.automount
* | |-sys-fs-fuse-connections.mount
* | |-sys-kernel-config.mount
* | |-sys-kernel-debug.mount
* | |-systemd-ask-password-console.path
* | |-systemd-binfmt.service
* | |-systemd-firstboot.service
* | |-systemd-hwdb-update.service
* | |-systemd-journal-catalog-update.service
* | |-systemd-journal-flush.service
* | |-systemd-journald.service
* | |-systemd-machine-id-commit.service
* | |-systemd-modules-load.service
* | |-systemd-random-seed.service
* | |-systemd-sysctl.service
* | |-systemd-tmpfiles-setup-dev.service
* | |-systemd-tmpfiles-setup.service
* | |-systemd-udev-trigger.service
* | |-systemd-udevd.service
* | |-systemd-update-done.service
* | |-systemd-update-utmp.service
* | |-systemd-vconsole-setup.service
* | |-cryptsetup.target
* | |-local-fs.target
* | | |--.mount
* | | |-boot.mount
* | | |-rhel-import-state.service
* | | |-rhel-readonly.service
* | | `-systemd-remount-fs.service
* | `-swap.target
* | `-dev-mapper-centos_centosswap.swap
* `-timers.target
* `-systemd-tmpfiles-clean.timer
Listing 2.23 Auszug der Abhängigkeiten von »sshd«
Folgender Befehl wurde in diesem Abschnitt behandelt:
-
systemctl list-dependencies <UNIT>
2.5.8 Logs mit »journald«
Wie bereits zu Beginn von Abschnitt 2.5 beschrieben, bringt systemd sein eigenes LoggingFramework namens journald mit. Dass die Log-Dateien binär gespeichert werden, um sie länger und fälschungssicher – so zumindest der Anspruch der systemd-Entwickler – speichern zu können, ist jedoch ein großer Kritikpunkt der Linux-Community. Allerdings hat journald Charme und bringt außer der Umgewöhnung auch einige Vorteile mit, wie beispielsweise dass Fehler in den Log-Dateien in Rot markiert werden und so eher auffallen.
Rufen Sie beispielsweise journalctl ohne weitere Parameter auf, bekommen Sie einen interaktiven Auszug aller Log-Dateien, so wie sie früher in /var/log/syslog oder /var/log/messages landeten. Hier können Sie auch durch Eingabe eines großen »F« in den Follow-Modus wechseln. Mit dem Parameter -f oder --follow wird Ihnen das Log analog zu einem tail -f angezeigt. Wenn Sie die letzten 20 Log-Einträge anschauen wollen, benutzen Sie -n 20 oder --lines=20. Der Parameter --reverse zeigt die Einträge in umgekehrter Reihenfolge an.
Einträge eines bestimmten Zeitraums grenzen Sie durch --since und --until ein. Dabei wird ein Datum in der Form "2018-07-30 18:17:16" ausgewertet. Ohne Datum wird der heutige Tag angenommen, ohne Sekunden wird 0 (null) angenommen, Sonderausdrücke wie yesterday, today, tomorrow oder now sind möglich.
Einer der wichtigsten Parameter ist -u oder --unit=, womit nur die Log-Dateien einer einzelnen Unit oder eines Satzes an Units ausgegeben werden. Wollen Sie beispielsweise die Log-Einträge des SSH-Daemons vom 5. August 2018 zwischen 13:00 Uhr und 14:00 Uhr haben, geben Sie den Befehl aus Listing 2.24 ein:
# journalctl --since="2018-08-05 13:00" --until="2018-08-05 14:00" \
--unit=sshd.service
-- Logs begin at Fr 2018-08-05 07:19:24 CEST, end at Fr 2018-08-05 15:56:51 CEST. --
Aug 05 13:07:24 centos sshd[13128]: reverse mapping checking getaddrinfo for \
1-2-3-4.a.b [1.2.3.4] failed - POSSIBLE BREAK-IN\
ATTEMPT!
Aug 05 13:07:24 centos sshd[13130]: reverse mapping checking getaddrinfo for \
1-2-3-4.a.b [1.2.3.4] failed - POSSIBLE BREAK-IN\
ATTEMPT!
Aug 05 13:07:24 centos sshd[13128]: Connection closed by 1.2.3.4 [preauth]
Aug 05 13:07:24 centos sshd[13130]: Connection closed by 1.2.3.4 [preauth]
Listing 2.24 Log-Auszug des SSH-Daemons
[+] Die Logs von journald werden nach einem Neustart gelöscht. Wenn Sie das nicht wollen, sollten Sie das Verzeichnis /var/log/journal anlegen und das Signal SIGUSR1 an den journald-Prozess senden. Damit werden die Logs in dem angegebenen Verzeichnis persistiert, sodass sie maximal zehn Prozent der Größe des Dateisystems belegen. Weitere Konfigurationen nehmen Sie in der Datei /etc/systemd/journald.conf vor.
Folgender Befehl wurde in diesem Abschnitt behandelt:
-
journalctl
2.5.9 Abschlussbemerkung
Die hier vorgestellten Befehle und Direktiven bilden nur einen Ausschnitt der Möglichkeiten von systemd ab. Dieser Ausschnitt ist jedoch eine gute Basis für weitere Schritte. Eigene Skripte und Job-Definitionen können Sie damit bereits jetzt erstellen. Über die Manpages können Sie noch einige andere Kommandos und Subkommandos finden.