Zum Inhalt springen

Systemd/Dienste

Aus Foxwiki
Die 5 zuletzt angesehenen Seiten:  Shutdown/Befehl » Moodle/Language » Diskussion:Clear » Systemd/Dienste
Version vom 7. April 2025, 14:41 Uhr von Dirkwagner (Diskussion | Beiträge) (Textersetzung - „http://“ durch „https://“)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)

Dienste konfigurieren

Systemd startet im Bootprozess unter anderem einen SSH-Daemon, hängt eine Partition ein und konfiguriert eine Netzwerkschnittstelle

Alle diese einzelnen kleinen Aufgaben bezeichnet Systemd als Units

  • Die wiederum lassen sich noch einmal nach ihrem jeweiligen Einsatzzweck klassifizieren

So kümmern sich Service-Units um das Starten und Stoppen von Diensten, Mount- und Automount-Units helfen beim Ein- und Aushängen von Dateisystemen, während wiederum Socket-Units die benötigten Sockets öffnen

Für jede dieser Units muss der Administrator eine eigene kleine Konfigurationsdatei erstellen

  • Ihr Dateiname setzt sich aus dem Namen der Unit und dem entsprechenden Unit-Typ zusammen

Beim SSH-Daemon handelt es sich zweifelsohne um einen Dienst, weshalb die Konfigurationsdatei sshd.service heißt

Systemd bringt bereits Unit-Dateien für die wichtigsten Systemdienste mit

  • Diese lagern normalerweise im Unterverzeichnis "/usr/lib/systemd/system/" (in früheren Systemd-Versionen "/lib/systemd/system")

Zusätzlich existiert noch das Verzeichnis "/etc/systemd/system/"

  • In ihm sollen Administratoren ihre eigenen Unit-Dateien speichern
  • Alle dort gelagerten Unit-Dateien haben Vorrang vor den Einstellungen ihrer gleichnamigen Kolleginnen unter "/usr/lib/systemd/system/"

Diese Trennung hat den Vorteil, dass ein Update der Distribution keine geänderte Unit-Datei überschreibt

Listing sshd.service

[Unit]
Description=OpenSSH server daemon
After=syslog.target network.target auditd.service
[Service]
EnvironmentFile=/etc/sysconfig/sshd
ExecStartPre=/usr/sbin/sshd-keygen
ExecStart=/usr/sbin/sshd -D $OPTIONS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s
[Install]
WantedBy=multi-user.target

Target-Auswahl

Systemd startet immer automatisch das "default.target"

  • Ein anderes Target können Sie am Bootprompt über den Parameter "systemd.unit" vorgeben

Mit "systemd.unit=rescue.target" würde Systemd beispielsweise ein Rettungssystem starten. "default.target" ist zudem für gewöhnlich nur ein symbolischer Link auf ein anderes Target, bei einem Desktop-System etwa auf "graphical.target"

Wer ein anderes Target zum Standard küren möchte, muss somit lediglich den Link umbiegen

  • In folgendem Fall würde Systemd zukünftig immer in das "multi-user.target" starten:
ln -s /usr/lib/systemd/system/multi-user.target
/etc/systemd/system/default.target

Um den Prozess eines Dienstes abzuschießen, müssen Sie lediglich den Namen der Service-Unit kennen, um den Rest kümmert sich "systemctl"

Im folgenden Beispiel sendet Systemd ein SIGTERM-Signal an den SSH-Daemon:

systemctl kill --signal=SIGTERM sshd.service

Das Kommando "systemctl reboot" startet das System neu, "systemctl poweroff" fährt das System kontrolliert herunter und schaltet es aus

  • Ergänzend zu "po­weroff" gibt es noch "suspend", "hibernate" und "hybrid-sleep", die in die entsprechenden Schlafzustände wechseln

Zu diesen Befehlen gibt es noch handliche Kurzformen, anstelle von "systemctl reboot" funktioniert beispielsweise auch einfach "reboot"

Datei:Bild2.png

Bild 3: Dieses System mit CentOS 7 hat knapp 50 Sekunden für den kompletten Start benötigt

  • Gebremst haben vor allem Plymouth und die Firewall (in Form von "firewalld")
Changing the Default Boot Target
$ ln -sf /usr/lib/systemd/system/multi-user.target /etc/systemd/system/default.target

This line makes the multi user target (i.e

  • full system, but no graphical UI) the default target to boot into
  • This is kinda equivalent to setting runlevel 3 as the default runlevel on Fedora/sysvinit systems
$ ln -sf /usr/lib/systemd/system/graphical.target /etc/systemd/system/default.target

This line makes the graphical target (i.e

  • full system, including graphical UI) the default target to boot into
  • Kinda equivalent to runlevel 5 on fedora/sysvinit systems
  • This is how things are shipped by default

Unit Files

Ein zentrales Konzept von systemd sind die Unit-Files

  • Diese ersetzen die Init-Skripte von anderen Systemen und sind wesentlich einfacher aufgebaut

Unit Typen

Es gibt verschiedene Arten von Unit Files, nachfolgend ein paar Beispiele:


Unit Files
Dienste Typen
.service Typ für normale Dienste
.target Zieltyp, dient zum Beispiel als Ersatz für Runlevels (graphical.target), aber auch für Zwischenschritte (network.target, local-fs.target, ...)
.mount Typ für Mountpoints, meist automatisch durch systemd-fstab-generator erzeugt
.socket Typ für Socket Activation von Diensten


Units gleichzeitig starten

Ein neu gestarteter Server sollte ein funktionierendes Netzwerk bieten, den Multiuser-Betrieb unterstützen und schließlich auch noch den SSH-Daemon zünden

  • Systemd muss folglich automatisch ein paar fest vorgegebene Units starten

Um das zu erleichtern, lassen sich mehrere Units zu einer Gruppe zusammenfassen, dem sogenannten Target

  • Systemd kann dann alle Units aus einem Target auf einen Schlag starten beziehungsweise aktivieren

Einige praxisrelevante Targets liegen Systemd bereits bei

  • So umfasst das Target "multi-user.target" alle Units, die für den Multiuser-Netzwerkbetrieb notwendig sind, während das Target "graphical.target" zu einem Desktop mit grafischer Benutzeroberfläche führt

Die Targets ersetzen damit gleichzeitig die alten Runlevel von SysV-Init: Weist der Administrator Systemd an, das Target "graphical.target" zu aktivieren, sitzt er anschließend vor einem System mit grafischer Benutzeroberfläche, wie es üblicherweise der Runlevel 5 zur Verfügung stellt

Targets sind selbst wieder normale Units

  • Das hat den Vorteil, dass ein Target ein anderes verwenden beziehungsweise starten kann

Das nutzen die mitgelieferten Targets massiv aus: "graphical.target" aktiviert etwa erst dann die grafische Benutzeroberfläche, wenn "multi-user.target" das restliche System eingerichtet hat

What units does a unit depend on?

For example, if you want to figure out which services a target like multi-user.target pulls in, use something like this:

$ systemctl show -p "Wants" multi-user.target

Wants=rc-local.service avahi-daemon.service rpcbind.service NetworkManager.service acpid.service dbus.service atd.service crond.service auditd.service ntpd.service udisks.service bluetooth.service cups.service wpa_supplicant.service getty.target modem-manager.service portreserve.service abrtd.service yum-updatesd.service upowerd.service test-first.service pcscd.service rsyslog.service haldaemon.service remote-fs.target plymouth-quit.service systemd-update-utmp-runlevel.service sendmail.service lvm2-monitor.service cpuspeed.service udev-post.service mdmonitor.service iscsid.service livesys.service livesys-late.service irqbalance.service iscsi.service netfs.service

Instead of "Wants" you might also try "WantedBy", "Requires", "RequiredBy", "Conflicts", "ConflictedBy", "Before", "After" for the respective types of dependencies and their inverse

Aufbau der Unit-Dateien

Unit-Dateien sind recht einfach aufgebaut

  • Das Listing "sshd.service" zeigt als Beispiel die Unit-Datei des SSH-Daemons aus CentOS 7 und damit schon einen etwas umfangreicheren Vertreter
  • Jede Unit-Datei ist in mehrere Abschnitte unterteilt, jede Zeile enthält genau eine Einstellung

Im Abschnitt "[Unit]" liefert "Description=" zunächst eine kurze Beschreibung der Unit

  • Hinter "After=" folgen, jeweils durch ein Leerzeichen getrennt, alle Units und Targets, die der Dienst zwingend für seine Arbeit benötigt

Im Beispiel startet der SSH-Daemon erst dann (und wirklich erst dann), wenn die Logging-Dienste ("syslog.target"), das Netzwerk ("network.target") und der Audit-Dienst ("auditd.service") verfügbar sind

Neben "After" gibt es noch die etwas weniger restriktiven "Requires" und "Wants": Alle Units hinter "Requires=" startet Systemd parallel mit der neu definierten Unit

Deaktiviert der Administrator eine der aufgeführten Units, knipst Systemd auch automatisch der neuen Unit das Licht aus

  • Sämtliche hinter "Wants=" gelisteten Units startet Systemd ebenfalls parallel mit der neu definierten Unit

Letztgenannte aktiviert Systemd aber selbst dann, wenn eine der anderen Units abstürzt oder aus einem anderen Grund nicht verfügbar ist

Im Abschnitt "[Service]" folgen alle Informationen, die Systemd zum Aktivieren des Dienstes benötigt

  • Der Befehl zum Starten des SSH-Daemons findet sich hinter "ExecStart=", alle anderen Angaben sind optional
  • Im Listing "sshd.service" holt zunächst "EnvironmentFile=" ein paar Umgebungsvariablen aus der angegebenen Datei hinzu
  • Das Programm hinter "ExecStartPre=" führt Systemd immer direkt vor dem eigentlichen Dienst aus

Wenn Systemd den Dienst beenden muss, schickt er ihm ein SIGTERM-Signal, auf das alle guten Prozesse reagieren sollten

  • Im Listing "sshd.service" sorgt "KillMode=process" noch dafür, dass Systemd nur den SSH-Daemon selbst, nicht aber seine Kindprozesse abwürgt
  • Lässt sich der Dienst anders als der SSH-Daemon nur mit einem speziellen Befehl herunterfahren, notiert man diesen hinter "ExecStop="

Mit welchem Kommando Systemd den Dienst neu startet, verrät "ExecReload="

  • Wann das passiert, bestimmt der Wert hinter "Restart="
  • In Listing "sshd.service" passiert das automatisch, wenn sich der SSH-Daemon unerwartet beendet ("on-failure")

Mit dem Neustart wartet Systemd zudem sicherheitshalber 42 Sekunden ("RestartSec=42s")

  • Diese Verzögerung soll unter anderem verhindern, dass der Dienst immer wieder schnell hintereinander neu startet und so unnötig Rechenzeit frisst

Der Abschnitt "[Install]" verrät schließlich noch, zu welchen Targets die Unit gehört

  • Im Listing sorgt die letzte Zeile dafür, dass der SSH-Daemon immer zusammen mit dem Target "multi-user.target" startet

Alternativ können Sie die Zugehörigkeit auch über symbolische Links vorgeben

  • Dazu erstellen Sie zunächst im Verzeichnis "/etc/systemd/system/" ein neues Unterverzeichnis
  • Dieses erhält den Namen des Targets mit einem angehängten ".wants"

Möchten Sie beispielsweise den SSH-Daemon im Target "multi-user.target" starten lassen, erstellen Sie das Unterverzeichnis "multi-user.target.wants"

  • In ihm setzen Sie dann wiederum einen symbolischen Link auf die Unit-Datei des Dienstes, im Beispiel also auf /lib/systemd/system/sshd.service

Damit startet dann der SSH-Daemon immer dann, wenn Systemd das Target "multi-user.target" aktiviert

Change a service file

rpm keeps overwriting it in /usr/lib/systemd/system all the time

  • How to handle this?

The recommended way is to copy the service file from /usr/lib/systemd/system to /etc/systemd/system and edit it there

  • The latter directory takes precedence over the former, and rpm will never overwrite it

If you want to use the distributed service file again you can simply delete (or rename) the service file in /etc/systemd/system again

My service foo.service

as distributed by my operating system vendor is only started when (a connection comes in or some hardware is plugged in)

  • I want to have it started always on boot, too
  • What should I do?

Simply place a symlink from that service file in the multi-user.target.wants/ directory (which is where you should symlink everything you want to run in the old runlevel 3, i.e

  • the normal boot-up without graphical UI

It is pulled in by graphical.target too, so will be started for graphical boot-ups, too):

  1. ln -sf /usr/lib/systemd/system/foobar.service /etc/systemd/system/multi-user.target.wants/foobar.service
  2. systemctl daemon-reload

Services After the Network is up

My service is ordered after network.target but at boot it is still called before the network is up

  • What's going on?

That's a long story, and that's why we have a wiki page of its own about this: Running Services After the Network is up (https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget)

RT scheduling

Whenever my service tries to acquire RT scheduling for one of its threads this is refused with EPERM even though my service is running with full privileges

  • This works fine on my non-systemd system!

By default, systemd places all systemd daemons in their own cgroup in the "cpu" hierarchy

Unfortunately, due to a kernel limitation, this has the effect of disallowing RT entirely for the service