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.
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
Links
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.