habilitar y deshabilitar un servicio systemd en Python usando DBus

El próximo picockpit-client reacciona a los eventos de borrado del frontend desactivando su servicio (No obstante, la aplicación seguirá instalada).

Del mismo modo, cuando decidas volver a ejecutar picockpit-client connect, el servicio se volverá a activar y se iniciará automáticamente por ti.

Esto es posible utilizando el Interfaz DBus de Python.

El DBus es un sistema de bus para interactuar con otras aplicaciones. Las aplicaciones y los servicios del sistema publican una determinada interfaz sobre el DBus, que usted puede utilizar.

Así es como se hace:

desactivar un servicio:

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

imagen

Abrimos el SystemBus - hay un SessionBus también ( dbus.SessionBus() ) que se utiliza para interactuar con una sesión de usuario. Sin embargo, en este caso queremos acceder a los servicios del sistema.

hasta el gestor estas son llamadas "estándar" - para acceder a systemd hay que pasar por ellas.

la siguiente línea es donde instruimos al gestor para que desactive los archivos de la unidad. Aquí hay algunas notas más sobre eso:

  • la primera variable es un array de cadenas - incluso si quieres desactivar sólo un servicio, lo pasas como un array.
  • se pasa el nombre del servicio incluyendo la parte '.service' - por ejemplo picockpit-client.service
  • la segunda variable es necesaria y sería False para desactivar para cada arranque (y True para desactivar sólo para este tiempo de ejecución)

Esta es la firma para DisableUnitFiles de la documentación oficial de DBus / systemd / Freedesktop.org:

imagen

Tenga en cuenta que es importante proporcionar todas las variables cuando se interactúa con la interfaz DBus. Son no opcional y "establecer a los valores predeterminados sanos", como se puede utilizar de muchas otras interfaces / API.

Por último, he leído en Internet que los cambios deben ser confirmados mediante el uso de manager.Reload() (la documentación dice: Reload() puede ser invocado para recargar todos los archivos de la unidad)

habilitar e iniciar un servicio:

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

imagen

Similar a lo anterior, con la siguiente diferencia para EnableUnitFiles:

  • hay dos variables booleanas después de la matriz de cadenas que NECESITAN ser pasadas
  • la primera variable booleana, como en el caso anterior, determina si el servicio debe estar habilitado sólo para este tiempo de ejecución (True) o en general (False);
  • la segunda variable booleana se describe, de forma algo críptica, como "La segunda controla si los enlaces simbólicos que apuntan a otras unidades serán reemplazados si es necesario". He decidido ponerla a True.

Aquí está la firma EnableUnitFiles de la documentación:

imagen

Mirándolo bien, mi elección de "True" posiblemente no sea sensata para otras aplicaciones ("forzar" implica una especie de anulación de la seguridad).

Finalmente, ReiniciarUnidad para iniciar realmente el servicio:

  • tenga en cuenta que esto toma un valor de cadena, no una matriz de cadenas
  • el segundo valor es una cadena que especifica el modo. Consulte la sección documentación oficial para los diferentes modos que son posibles.

Aquí está la firma de RestartUnit:

imagen

Nota: No manejo los valores de retorno, idealmente y especialmente para aplicaciones críticas, usted querría mirar en eso - refiérase al documentación oficial.

Errores

Desajuste de la firma

ERROR:dbus.connection:Imposible establecer los argumentos (['picockpit-client.service'],) según la firma 'asb': : Se han encontrado más elementos en la firma de D-Bus que en los argumentos de Python

Si obtiene un error como el anterior, compruebe si está pasando todos los parámetros tal y como requiere la firma en la documentación.

En este caso me había (equivocado):

manager.DisableUnitFiles(['picockpit-client.service'])

en lugar de la correcta:

manager.DisableUnitFiles(['picockpit-client.service'], False)

Asegúrese también de comprobar si está pasando una cadena (s), donde una matriz de cadenas (como) es necesario.


Ref