Sie benötigen mehrere Dinge, damit dies funktioniert.
- Aktivieren Sie die Ausführung von Benutzerdiensten zum Startzeitpunkt ohne Benutzeranmeldung (systemd verweilen).
- Eine systemd-Socket-Datei, um den D-Bus-Socket anzugeben, den systemd zuweisen soll.
- Ein systemd-Dienst zum Starten des gestarteten D-Bus-Sitzungsbusses, der dann die Umgebungsvariable DBUS_SESSION_BUS_ADDRESS für andere systemd-Dienste festlegt.
- Stellen Sie sicher, dass Ihre systemd-
my-dbus-client.service
Dateien Type=dbus
vom dbus.socket
Gerät stammen oder von diesem abhängen , um sicherzustellen, dass sie den dbus-Sitzungsbus-Socket zuweisen, und starten Sie den dbus-Sitzungsdienst, falls dieser noch nicht gestartet wurde.
Damit Systemd-Dienste für einen bestimmten Benutzer zum Startzeitpunkt ohne Anmeldung gestartet werden können, müssen Sie zunächst das Verweilen des Systemd-Benutzers aktivieren. Dies muss bei der Konfiguration nur einmal als Root erfolgen, um es für einen Benutzer zu aktivieren:
# loginctl enable-linger otheruser
Wenn Sie sich auf einem Debian-basierten System befinden, können Sie für die nächsten beiden Schritte einfach das Paket dbus-user-session packen:
# apt-get install dbus-user-session
Wenn Sie eine andere Distribution verwenden, möchten Sie dies manuell tun oder einfach nur verstehen, wie es weitergeht. Andernfalls überspringen Sie die Erstellung von dbus.service
und dbus.socket
.
Erstellen Sie die Datei /usr/lib/systemd/user/dbus.socket
(beachten Sie, bei einigen Distributionen befindet sich möglicherweise das Benutzerverzeichnis /lib
anstelle von /usr/lib
) mit dem folgenden Inhalt:
[Unit]
Description=D-Bus User Message Bus Socket
[Socket]
ListenStream=%t/bus
ExecStartPost=-/bin/systemctl --user set-environment DBUS_SESSION_BUS_ADDRESS=unix:path=%t/bus
[Install]
WantedBy=sockets.target
Also=dbus.service
Die Weitergabe DBUS_SESSION_BUS_ADDRESS
an alle Dienste, die Ihr Hauptanliegen war, wird in der folgenden ExecPostStart
Zeile behandelt. Für alle folgenden Dienste wird diese Einstellung festgelegt.
%t
wird ersetzt durch XDG_RUNTIME_DIR
- ein vorübergehendes Verzeichnis, /run
das von systemd erstellt wurde und für die Benutzersitzung spezifisch ist, in die Sie Dateien einfügen können. Wenn Sie diesen Socket an einem anderen Ort erstellen möchten, gibt es keinen Grund, warum Sie dies nicht können. Stellen Sie einfach sicher, dass es irgendwo vorübergehend ist, oder es wird beim Neustart / Herunterfahren der Sitzung bereinigt.
Ich hatte einige Probleme beim Versuch, den dbus-Unix-Socket zu einem abstrakten zu machen - systemd schien die Form unix:abstract=
oder das @
Präfix aus irgendeinem Grund nicht zu mögen .
Erstellen Sie nun die Datei /usr/lib/systemd/user/dbus.service
mit folgendem Inhalt:
[Unit]
Description=D-Bus User Message Bus
Requires=dbus.socket
[Service]
ExecStart=/usr/bin/dbus-daemon --session --address=systemd: --nofork --nopidfile --systemd-activation
ExecReload=/usr/bin/dbus-send --print-reply --session --type=method_call --dest=org.freedesktop.DBus / org.freedesktop.DBus.ReloadConfig
[Install]
Also=dbus.socket
Es gibt ein bisschen Magie, die hier hinter den Kulissen von systemd vor sich geht, um den bereits erstellten Unix-Socket an den dbus-Daemon zu übergeben. Systemd verwendet die Informationen von dbus.socket
, um den Socket zu erstellen, und sein Dateideskriptor wird in der Umgebungsvariablen festgelegt LISTEN_FDS
, die an die übergeben wird dbus-daemon
. Die oben aufgeführten speziellen Optionen veranlassen dbus-daemon, den übergebenen Dateideskriptor zu verwenden, anstatt einen neuen zu erstellen. Auf diese Weise können dbus-Clients parallel zum dbus-Daemon gestartet werden, ohne dass der Socket vorhanden sein muss.
Erstellen Sie abschließend Ihre eigenen systemd-Benutzerdienste, und stellen Sie sicher, dass Sie entweder den Typ auf Type=dbus
, BusName=
den Namen eines der von diesem Dienst registrierten dbus-Dienstnamen oder Requires=dbus.socket
den Abschnitt "Einheit" festlegen. Hier ist ein Beispiel:
[Unit]
Description=Config Server Startup
[Service]
Type=dbus
BusName=com.example.app.configuree
ExecStart=/opt/example/app/configuration_server
Restart=on-failure
[Install]
WantedBy=default.target
Sie können sie an einer von mehreren Stellen platzieren: - $HOME/.config/systemd/user
-/usr/lib/systemd/user
Aktivieren Sie Ihre Dienste mit systemctl --user enable <service name>
und starten Sie neu, und alles sollte funktionieren.
Verweise:
man loginctl
zum Verweilen
man pam_systemd
für XDG_RUNTIME_DIR info
man systemd.service
für Typ = dbus, Busname = und implizite Abhängigkeit von dbus.socket
man sd_listen_fds
Informationen zur Umgebungsvariablen LISTEN_FDS
- https://wiki.archlinux.org/index.php/Systemd/User - Allgemeine Informationen zu Systemd-Benutzersitzungen