abilitare e disabilitare un servizio systemd in Python usando DBus
Il prossimo picockpit-client reagisce agli eventi di cancellazione dal frontend disattivando il suo servizio (l'applicazione rimarrà comunque installata).
Allo stesso modo, quando decidi di eseguire di nuovo picockpit-client connect, il servizio sarà riabilitato e avviato automaticamente per te.
Questo è possibile usando il Interfaccia DBus Python.
il DBus è un sistema di bus per interagire con altre applicazioni. Le applicazioni e i servizi di sistema pubblicano una certa interfaccia sul DBus, che è possibile utilizzare.
Ecco come fare:
disattivare un servizio:
importazione dbus
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()
Apriamo il SystemBus - c'è anche un SessionBus ( dbus.SessionBus() ) che è usato per interagire con una sessione utente. In questo caso però vogliamo accedere ai servizi di sistema.
fino a manager queste sono chiamate "standard" - per accedere a systemd è necessario passare attraverso di esse.
la prossima linea è dove istruiamo il manager a DisableUnitFiles. Qui ci sono altre note su questo:
- la prima variabile è un array di stringhe - anche se si vuole disabilitare un solo servizio, lo si passa come array.
- passate il nome del vostro servizio includendo la parte '.service' - ad esempio picockpit-client.service
- la seconda variabile è richiesta e sarebbe False per disabilitare per ogni avvio (e True per disabilitare solo per questo runtime)
Ecco la firma per DisableUnitFiles da la documentazione ufficiale di DBus / systemd / Freedesktop.org:
Nota, è importante fornire tutte le variabili quando si interagisce con l'interfaccia DBus! Sono non opzionale e "impostato su sani default", come si potrebbe essere abituati da molte altre interfacce / API.
Infine, ho letto online che i cambiamenti devono essere impegnati usando manager.Reload() (la documentazione dice: Reload() può essere invocato per ricaricare tutti i file dell'unità)
abilitare e avviare un servizio:
importazione dbus
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')
Simile al precedente, con la seguente differenza per EnableUnitFiles:
- ci sono due variabili booleane dopo l'array di stringhe che hanno bisogno di essere passate in
- la prima variabile booleana, come sopra, determina se il servizio deve essere abilitato solo per questo runtime (True) o in generale (False);
- la seconda variabile booleana è, un po' cripticamente, descritta come: "La seconda controlla se i collegamenti simbolici che puntano ad altre unità devono essere sostituiti se necessario". Ho deciso di impostarla su True.
Ecco la firma EnableUnitFiles dalla documentazione:
Guardando la cosa, la mia scelta di "True" potrebbe non essere sensata per altre applicazioni ("force" implica una sorta di annullamento della sicurezza).
Finalmente, RestartUnit per avviare effettivamente il servizio:
- notare che questo prende un valore di stringa, non un array di stringhe
- il secondo valore è una stringa che specifica la modalità. Si prega di fare riferimento al documentazione ufficiale per i diversi modi che sono possibili.
Ecco la firma di RestartUnit:
Nota: non gestisco i valori di ritorno, idealmente e specialmente per applicazioni critiche, dovreste considerare questo aspetto - fate riferimento al documentazione ufficiale.
Errori
Mancata corrispondenza della firma
ERROR:dbus.connection:Impossibile impostare gli argomenti (['picockpit-client.service'],) secondo la firma 'asb': : Trovati più elementi nella firma D-Bus che negli argomenti Python
Se ottenete un errore come sopra, controllate se state passando tutti i parametri come richiesto dalla firma nella documentazione.
In questo caso avevo (sbagliato):
manager.DisableUnitFiles(['picockpit-client.service'])
invece di quello corretto:
manager.DisableUnitFiles(['picockpit-client.service'], False)
Assicuratevi anche di controllare se state passando una stringa (s), dove un array di stringhe (come) è richiesto.
Rif
- https://dbus.freedesktop.org/doc/dbus-python/tutorial.html
- https://www.freedesktop.org/wiki/Software/systemd/dbus/ <-la documentazione / API per Dbus / systemd