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()
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:
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')
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:
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:
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
- https://dbus.freedesktop.org/doc/dbus-python/tutorial.html
- https://www.freedesktop.org/wiki/Software/systemd/dbus/ <la documentación / API para Dbus / systemd