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()

immagine

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:

immagine

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')

immagine

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:

immagine

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:

immagine

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