Zum Hauptinhalt springen

Dienste als Benutzer mit Systemd verwalten

Seit Ubuntu Xenial wird systemd als Init-System eingesetzt. Zusätzlich zur systemweiten Instanz unterstützt systemd auch benutzerspezifische Instanzen.

Dies ermöglicht Ihnen, innerhalb Ihres Benutzeraccounts selbst verwaltete Dienste zu betreiben und zu kontrollieren.

Systemd unterstützt mehrere Arten von Units. Die meist verwendete Art ist die "Service Unit", welche einen Service oder Daemon definiert.

In diesem Artikel erläutern wir, wie man mit systemd interagiert und Services verwaltet.

Für die Interaktion mit der benutzerspezifischen Umgebung von systemd wird der Befehl systemctl --user verwendet. Die Konfiguration der user Units für systemd befindet sich im Verzeichnis ~/.config/systemd/user.

Systemd bringt einige neue Ansätze mit, die insbesondere darauf abzielen, die gestarteten Prozesse zu überwachen. Logausgaben können dabei direkt nach STDOUT/STDERR geschrieben werden, systemd reicht diese dann an das Journal weiter.

User Systemd Status

Der Befehl systemctl --user status zeigt alle durch systemd verwalteten Prozesse unter dem aktuellen Benutzer an. Im folgenden Beispiel ist neben der benutzerspezifischen systemd Instanz (init.scope) auch ein memcached Server (mymemcached.service) aktiv.

www-data@nine01-test:~ $ systemctl --user status
● nine01-test
State: running
Jobs: 0 queued
Failed: 0 units
Since: Fri 2021-09-17 17:12:02 CEST; 4 months 10 days ago
CGroup: /user.slice/user-33.slice/user@33.service
├─init.scope
│ ├─1634 /lib/systemd/systemd --user
│ └─1647 (sd-pam)
└─mymemcached.service
└─106393 /usr/bin/memcached -A -m 32 -p 11212 -u www-data -l 127.0.0.1 -P /home/www-data/memcached.pid

Falls Sie den Befehl systemctl innerhalb ihrer Crontab oder in Skripten verwenden möchten, so muss die Variable XDG_RUNTIME_DIR gesetzt sein.

export XDG_RUNTIME_DIR=/run/user/$UID

Verwalten eines Services

Sie können die folgenden Befehle verwenden um einen Service (neu) zu starten, zu stoppen oder den Status zu überprüfen.

Status

Es ist möglich den Status einer bestimmten Service Unit abzufragen. Hierzu muss der Servicename der Statusabfrage hinzugefügt werden. Anschliessend wird der Status, eine Übersicht der laufenden Prozesse sowie die letzten Zeilen des Journals angezeigt.

www-data@nine01-test:~ $ systemctl --user status mymemcached.service
● mymemcached.service - Custom memcached on port 11212
Loaded: loaded (/home/www-data/.config/systemd/user/mymemcached.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2022-01-26 13:27:43 CET; 24h ago
Docs: /a/Ws7sDLPoiTo
Main PID: 106393 (memcached)
CGroup: /user.slice/user-33.slice/user@33.service/mymemcached.service
└─106393 /usr/bin/memcached -A -m 32 -p 11212 -u www-data -l 127.0.0.1 -P /home/www-data/memcached.pid

Jan 26 13:27:43 nine01-test systemd[1634]: Started Custom memcached on port 11212.

Start

Um einen Service zu starten, verwenden Sie den Parameter start:

www-data@nine01-test:~ $ systemctl --user start mymemcached.service

Stoppen

Um einen Service zu stoppen, verwenden Sie den Parameter stop:

www-data@nine01-test:~ $ systemctl --user stop mymemcached.service

Restart

Um einen Service neu zu starten, verwenden Sie den Parameter restart:

www-data@nine01-test:~ $ systemctl --user restart mymemcached.service

Journal / Logs eines Services einsehen

Das "journal" wird mit journalctl abgerufen. Dabei kann mithilfe des Parameters --user-unit= gezielt nach einzelnen Service Units gefiltert werden.

www-data@nine01-test:~ $ journalctl --user-unit=mymemcached.service

Jan 26 13:27:43 nine01-test systemd[1634]: Started Custom memcached on port 11212.

Services aktivieren und deaktivieren

Um einen Service beim Booten zu starten, verwenden Sie den Befehl enable:

www-data@nine01-test:~ $ systemctl --user enable mymemcached.service
Created symlink from /home/www-data/.config/systemd/user/default.target.wants/mymemcached.service to /home/www-data/.config/systemd/user/mymemcached.service.

Um zu prüfen ob ein Service bereits aktiviert wurde, kann der Befehl systemctl --user is-enabled verwendet werden.

www-data@nine01-test:~ $ systemctl --user is-enabled mymemcached.service
enabled

Mit folgendem Befehl kann der automatische Start des Services deaktiviert werden:

www-data@nine01-test:~ $ systemctl --user disable mymemcached.service
Removed symlink /home/www-data/.config/systemd/user/default.target.wants/mymemcached.service.

Unit Files

Die Unit Files für die benutzerspezifische systemd Instanz werden im Verzeichnis ~/.config/systemd/user hinterlegt. Der Name der Datei definiert dabei den Namen sowie den Typ der Unit.

Die Datei ~/.config/systemd/user/mymemcached.service definiert eine Service Unit mit dem Namen "mymemcached".

Die Unit Beschreibung ist in drei Bereiche unterteilt.

Im Unit Abschnitt sind Metadaten über die Unit zu finden. Der zweite Abschnitt ist nach dem Unit-Typ benannt, beispielsweise Service. In diesem Abschnitt wird die Unit definiert. Der Install Abschnitt enthält Installations-Anweisungen für den Zeitpunkt der Aktivierung oder der Deaktivierung einer Unit.

Target unit configuration multi-user.target

Um sicherzustellen, dass ein Dienst während des Systemstarts gestartet wird, muss dieser auf WantedBy=default.target gesetzt werden. WantedBy=multi-user.target sollte darum nicht verwendet werden, da es in der Benutzerinstanz von systemd nicht verfügbar ist.

Im Abschnitt Target Units wird erklärt, wie falsch konfigurierte Dienste richtig konfiguriert werden können.

Simple Service

Dieses Beispiel startet einen memcached Server auf Port 11212. Der Unit Abschnitt definiert nur die Beschreibung und optional einen Hinweis auf die Dokumentation. Im Service Abschnitt ist definiert, mit welchen Befehlen der Service gestartet und gestoppt wird. Der Stop-Befehl ist optional. Beim Stoppen eines Services führt systemd, falls definiert, zunächst diesen Befehl aus, und entfernt danach alle übriggebliebenen Prozesse dieser Unit.

# ~/.config/systemd/user/mymemcached.service
[Unit]
Description=Custom memcached on port 11212
Documentation=https://docs.nine.ch/a/Ws7sDLPoiTo

[Service]
ExecStart=/usr/bin/memcached -A -m 32 -p 11212 -u www-data -l 127.0.0.1 -P /home/www-data/memcached.pid

[Install]
WantedBy=default.target

Forking Service

Systemd empfiehlt Services, sich nicht selbst zu "daemonizen", respektive ein Forking vorzunehmen. Falls ihre Anwendung auf diese Funktionalität angewiesen ist, muss dies systemd mitgeteilt werden. Setzen Sie hierzu die Option Type auf den Wert forking. In diesem Fall ist es sinnvoll das PIDFile anzugeben, mit welchem systemd den Hauptprozess ermitteln kann.

%h im folgenden Beispiel wird durch den Pfad des "Home" Verzeichnisses des Benutzers ersetzt und %p mit dem Namen der Unit. Mit solchen Platzhaltern (systemd spricht von Specifiers) können robustere und einfacher zu portierende Unit-Konfigurationen erstellt werden. Weitere Informationen zu den Specifiers finden Sie in der systemd.unit Manpage.

# ~/.config/systemd/user/mymemcached.service
[Unit]
Description=Custom memcached on port 11212
Documentation=https://docs.nine.ch/a/Ws7sDLPoiTo

[Service]
Type=forking
ExecStart=/usr/bin/memcached -A -m 32 -p 11212 -u www-data -l 127.0.0.1 -P %h/.%p.pid

[Install]
WantedBy=default.target

Template Service

Vorlagen (Templates) sind ein vielseitiges Werkzeug von systemd. Units, deren Name auf @ endet, werden von systemd als Vorlage behandelt.

Dies ermöglicht das Starten mehrerer Instanzen des selben Services unter verschiedenen Ports oder Sockets.

Wenn Sie folgendes Beispiel in einer Konfigurationsdatei namens mymemcached@.service speichern, können Sie die Units mymemcached@7777 und mymemcached@7778 starten, um zwei memcached Server auf Port 7777 bzw. 7778 zu starten.

Der Teil hinter dem @ wird dabei für den Platzhalter %i in die Vorlage eingefüllt.

# .config/systemd/user/mymemcached@.service
[Unit]
Description=Custom memcached on port %i
Documentation=https://docs.nine.ch/a/Ws7sDLPoiTo

[Service]
ExecStart=/usr/bin/memcached -A -m 32 -p %i -u www-data -l 127.0.0.1 -P /home/www-data/memcached-%i.pid

[Install]
WantedBy=default.target
systemctl --user enable mymemcached@7778.service
Created symlink /home/www-data/.config/systemd/user/default.target.wants/mymemcached@7778.service → /home/www-data/.config/systemd/user/mymemcached@.service.

www-data@nine01-test:~ $ systemctl --user start mymemcached@7778.service

www-data@nine01-test:~ $ systemctl --user status mymemcached@7778.service
● mymemcached@7778.service - Custom memcached on port 7778
Loaded: loaded (/home/www-data/.config/systemd/user/mymemcached@.service; indirect; vendor preset: enabled)
Active: active (running) since Thu 2022-01-27 08:55:58 CET; 7s ago
Docs: /a/Ws7sDLPoiTo
Main PID: 108919 (memcached)
CGroup: /user.slice/user-33.slice/user@33.service/mymemcached.slice/mymemcached@7778.service
└─108919 /usr/bin/memcached -A -m 32 -p 7778 -u www-data -l 127.0.0.1 -P /home/www-data/memcached-7778.pid

Jan 27 08:55:58 nine01-test systemd[1634]: Started Custom memcached on port 7778.

Erweiterte Konfigurationen

Vor- / Nachgelagerte Aufgaben

Wenn zusätzliche Befehle vor dem Starten oder nach dem Stoppen eines Services ausgeführt werden sollen, kann dies über die ExecStart- bzw. ExecStop-Optionen sowie das Pre- oder Post-Suffix definiert werden.

Um mehrere Aufgabe auszuführen, können diese Parameter mehrfach angegeben werden.

Wenn einem Befehl ein - vorangestellt wird, so ignoriert systemd den Rückgabewert der Ausführung - der Befehl darf also fehlschlagen. Bei Verzicht auf diese Option führt ein Fehler im Rahmen von ExecStartPre zum Abbruch des Startprozesses.

[Service]
ExecStartPre=/bin/mkdir -p /tmp/mytempdir
ExecStartPre=-/bin/false
ExecStartPost=/usr/bin/touch /tmp/mytempdir/started
ExecStopPost=/bin/rm -rf /tmp/mytempdir

Reload

Falls Ihre Anwendung in der Lage ist ohne Neustart Konfigurationsanpassungen einzulesen, so besteht die Möglichkeit, die Option ExecReload in der Unit- Konfiguration zu hinterlegen.

Systemd führt zum "Reload" den angegebenen Befehl aus, wobei die Prozess-ID des Hauptprozesses für den Platzhalter $MAINPID eingesetzt wird.

[Service]
ExecReload=/bin/kill -HUP $MAINPID

Restart

Durch den Restart-Parameter lässt sich steuern, wie systemd auf ein unerwartetes Beenden des Services reagiert.

Die Standardeinstellung ist no. Wird die Option auf always gesetzt, so führt systemd bei Beendigung automatisch einen Neustart des Services durch.

[Service]
Restart=always

Ohne weitergehende Überwachung des gestarteten Services ist die Option Restart=always dringend empfohlen. Zwar schliesst dies keine Störungen Ihres Services aus, die Auswirkungen werden allerdings verringert.

Umgebungsvariablen

Neben Konfigurationsdateien können Anwendungen auch durch Umgebungsvariablen gesteuert werden. Systemd ermöglicht es, das Arbeitsverzeichnis (WorkingDirectory) und Umgebungsvariablen (Environment) in der Unit-Konfiguration festzulegen.

Zusätzlich kann eine Datei angegeben werden, in der weitere Umgebungsvariablen hinterlegt werden. Diese kann beispielsweise Teil Ihrer Applikation sein und durch Ihre Deployments verwaltet werden.

Die im EnvironmentFile hinterlegten Variablen überschreiben die in der Unit-Konfiguration definierten Environment-Variablen.

Wird diese Option in der Unit-Konfiguration verwendet, so muss die angegebene Datei existieren. Wird dem Dateipfad ein - vorangestellt, so ignoriert systemd ein eventuelles Fehlen der Datei.

Die Einträge im EnvironmentFile werden im Format NAME=WERT erwartet.

[Service]
WorkingDirectory=/home/www-data/servicedir
Environment=ENV=production
EnvironmentFile=-/home/www-data/servicedir/.env

Target Units

Um sicherzustellen, dass ein Dienst während des Systemstarts gestartet wird, muss dieser auf WantedBy=default.target gesetzt werden. WantedBy=multi-user.target sollte darum nicht verwendet werden, da es in der Benutzerinstanz von systemd nicht verfügbar ist.

Wir senden Warnungen über falsch konfigurierte Dienste. Wenn Sie eine solche Warnung erhalten haben, finden Sie unten die Befehle, um die Konfiguration zu korrigieren.

Um alle falsch konfigurierten Dienste eines Benutzers aufzulisten, führen Sie den folgenden Befehl aus:

find ~/.config/systemd/user/*.target.*/ -type l -name "*.service" -not -path "*/default.target.*/*"

Wenn Dienste falsch konfiguriert sind, können sie durch die Konfiguration des richtigen "targets" behoben werden. Der folgende Befehl konfiguriert automatisch default.target und aktiviert die Dienste wieder:

find ~/.config/systemd/user/*.target.wants/ -type l -name "*.service" -not -path "*/default.target.wants/*" -print0 |
while IFS= read -r -d '' service; do
sed -i --follow-symlinks 's/^WantedBy=.*/WantedBy=default.target/' "$service"
systemctl --user reenable "$(basename $service)"
done

Weitere Informationen und Optionen zu Unit-Konfigurationen können in der systemd.unit Manpage gefunden werden. Für Service Units sind auch die systemd.service und systemd.exec Manpages zu empfehlen.