Aktivierung und Deaktivierung eines systemd-Dienstes in Python mit DBus
Der kommende picockpit-Client reagiert auf Löschvorgänge aus dem Frontend durch Deaktivierung seines Dienstes (die Anwendung bleibt jedoch installiert).
Wenn Sie sich entscheiden, picockpit-client connect erneut auszuführen, wird der Dienst wieder aktiviert und automatisch für Sie gestartet.
Dies ist möglich mit Hilfe der Python DBus-Schnittstelle.
Der DBus ist ein Bussystem für die Interaktion mit anderen Anwendungen. Die Anwendungen und Systemdienste veröffentlichen eine bestimmte Schnittstelle über den DBus, die Sie nutzen können.
Und so geht's:
einen Dienst zu deaktivieren:
dbus importieren
system_bus = dbus.SystemBus()
systemd1 = system_bus.get_object('org.freedesktop.systemd1', '/org/freedesktop/systemd1')
manager = dbus.Interface(systemd1, 'org.freedesktop.systemd1.Manager')
manager.DisableUnitFiles(['picockpit-client.service'], False)manager.Reload()
Wir öffnen die SystemBus - gibt es auch einen SessionBus ( dbus.SessionBus() ), der für die Interaktion mit einer Benutzersitzung verwendet wird. In diesem Fall wollen wir jedoch auf Systemdienste zugreifen.
bis zum Manager sind dies "Standard"-Aufrufe - um auf systemd zuzugreifen, müssen Sie sie durchlaufen.
In der nächsten Zeile weisen wir den Manager an, DisableUnitFiles zu verwenden. Hier sind einige weitere Hinweise dazu:
- die erste Variable ist ein Array von Strings - auch wenn Sie nur einen Dienst deaktivieren wollen, übergeben Sie ihn als Array.
- geben Sie den Namen Ihres Dienstes einschließlich des Teils ".service" ein - z. B. picockpit-client.service
- die zweite Variable ist erforderlich und müsste False lauten, um sie bei jedem Start zu deaktivieren (und True, um sie nur für diese Laufzeit zu deaktivieren)
Hier ist die Signatur für DisableUnitFiles von die offizielle DBus / systemd / Freedesktop.org Dokumentation:
Beachten Sie, dass es wichtig ist, alle Variablen anzugeben, wenn Sie mit der DBus-Schnittstelle interagieren! Sie sind nicht optional und "set to sane defaults", wie man es von vielen anderen Schnittstellen / APIs gewohnt ist.
Schließlich habe ich im Internet gelesen, dass die Änderungen mit Hilfe von manager.Reload() (Die Dokumentation sagt: Reload() kann aufgerufen werden, um alle Unit-Dateien neu zu laden)
einen Dienst aktivieren und starten:
dbus importieren
system_bus = dbus.SystemBus()
systemd1 = system_bus.get_object('org.freedesktop.systemd1', '/org/freedesktop/systemd1')
manager = dbus.Interface(systemd1, 'org.freedesktop.systemd1.Manager')
manager.EnableUnitFiles(['picockpit-client.service'], False, True)
manager.Reload()
job = manager.RestartUnit('picockpit-client.service', 'fail')
Ähnlich wie oben, mit dem folgenden Unterschied für EnableUnitFiles:
- Es gibt zwei boolesche Variablen nach dem Array von Strings, die übergeben werden müssen
- die erste boolesche Variable bestimmt, wie oben, ob der Dienst nur für diese Laufzeit (True) oder generell (False) aktiviert werden soll;
- die zweite boolesche Variable wird, etwas kryptisch, wie folgt beschrieben: "Die zweite steuert, ob Symlinks, die auf andere Einheiten verweisen, bei Bedarf ersetzt werden sollen.". Ich habe beschlossen, sie auf True zu setzen.
Hier ist die EnableUnitFiles-Signatur aus der Dokumentation:
Die von mir gewählte Einstellung "True" ist für andere Anwendungen möglicherweise nicht sinnvoll ("force" impliziert eine Art Aufhebung der Sicherheit).
Endlich, NeustartEinheit um den Dienst tatsächlich zu starten:
- beachten Sie, dass dies einen String-Wert, nicht ein Array von Strings benötigt
- der zweite Wert ist eine Zeichenkette, die den Modus angibt. Bitte beziehen Sie sich auf die offizielle Dokumentation für die verschiedenen Modi, die möglich sind.
Hier ist die RestartUnit-Signatur:
Hinweis: Ich behandle die Rückgabewerte nicht. Idealerweise und insbesondere bei kritischen Anwendungen sollten Sie sich damit befassen - siehe die offizielle Dokumentation.
Fehler
Unstimmigkeit der Signatur
ERROR:dbus.connection:Unable to set arguments (['picockpit-client.service'],) according to signature 'asb': : In der D-Bus-Signatur wurden mehr Elemente gefunden als in den Python-Argumenten
Wenn Sie eine Fehlermeldung wie oben erhalten, überprüfen Sie, ob Sie alle Parameter so übergeben, wie es die Signatur in der Dokumentation verlangt.
In diesem Fall hatte ich (falsch):
manager.DisableUnitFiles(['picockpit-client.service'])
statt der richtigen:
manager.DisableUnitFiles(['picockpit-client.service'], False)
Überprüfen Sie auch, ob Sie eine Zeichenkette übergeben (s), wobei ein Array von Zeichenketten (als) ist erforderlich.
Ref
- https://dbus.freedesktop.org/doc/dbus-python/tutorial.html
- https://www.freedesktop.org/wiki/Software/systemd/dbus/ <die Dokumentation / API für Dbus / systemd