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:

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:

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:

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:

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:

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:

[+] 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:

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:

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.