activer et désactiver un service systemd en Python en utilisant DBus

Le prochain picockpit-client réagit aux événements de suppression de l'interface. en désactivant son service (l'application restera toutefois installée).

De même, lorsque vous décidez de lancer picockpit-client connect à nouveau, le service sera réactivé et démarré automatiquement pour vous.

Ceci est possible en utilisant le Interface Python DBus.

Le DBus est un système de bus permettant d'interagir avec d'autres applications. Les applications et les services du système publient une certaine interface sur le DBus, que vous pouvez utiliser.

Voici comment procéder :

désactiver un service :

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

image

Nous ouvrons le SystemBus - il existe également un SessionBus ( dbus.SessionBus() ) qui est utilisé pour interagir avec une session utilisateur. Dans ce cas, nous voulons cependant accéder aux services du système.

jusqu'au manager, ce sont des appels "standard" - pour accéder à systemd, il faut passer par eux.

la ligne suivante est celle où nous demandons au gestionnaire de DisableUnitFiles. Voici quelques notes supplémentaires à ce sujet :

  • la première variable est un tableau de chaînes de caractères - même si vous voulez désactiver un seul service, vous le passez comme un tableau.
  • vous indiquez le nom de votre service, y compris la partie '.service', par exemple picockpit-client.service
  • la deuxième variable est nécessaire et doit être False pour désactiver à chaque démarrage (et True pour désactiver seulement pour ce runtime).

Voici la signature pour DisableUnitFiles de la documentation officielle DBus / systemd / Freedesktop.org:

image

Attention, il est important de fournir toutes les variables lors de l'interaction avec l'interface DBus ! Ils sont pas facultatif et "défini par des valeurs par défaut saines", comme vous pouvez l'être à partir de nombreuses autres interfaces / API.

Enfin, j'ai lu en ligne que les changements doivent être validés en utilisant manager.Reload() (la documentation dit : Reload() peut être invoqué pour recharger tous les fichiers de l'unité)

activer et démarrer un service :

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

image

Similaire à ce qui précède, avec la différence suivante pour EnableUnitFiles :

  • il y a deux variables booléennes après le tableau de chaînes de caractères qui doivent être passées dans le tableau.
  • la première variable booléenne, comme ci-dessus, détermine si le service doit être activé pour ce seul runtime (True) ou de manière générale (False) ;
  • la deuxième variable booléenne est, de manière quelque peu cryptique, décrite comme : "La seconde contrôle si les liens symboliques pointant vers d'autres unités doivent être remplacés si nécessaire". J'ai décidé de la mettre à True.

Voici la signature EnableUnitFiles de la documentation :

image

En y réfléchissant, mon choix de "True" pourrait ne pas être judicieux pour d'autres applications ("force" implique une sorte de contournement de la sécurité).

Enfin, RestartUnit pour démarrer réellement le service :

  • notez que cela prend une valeur de chaîne de caractères, et non un tableau de chaînes de caractères
  • la deuxième valeur est une chaîne de caractères spécifiant le mode. Veuillez vous référer au documentation officielle pour les différents modes qui sont possibles.

Voici la signature de RestartUnit :

image

Remarque : je ne gère pas les valeurs de retour, idéalement et surtout pour les applications critiques, vous devriez vous pencher sur cette question - consultez la page Web de l'UE. documentation officielle.

Erreurs

Erreur de signature

ERROR:dbus.connection:Impossible de définir les arguments (['picockpit-client.service'],) selon la signature 'asb' : : Plus d'éléments trouvés dans la signature D-Bus que dans les arguments Python.

Si vous obtenez une erreur comme ci-dessus, vérifiez si vous passez tous les paramètres comme requis par la signature dans la documentation.

Dans ce cas, j'avais (mal) :

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

au lieu de la bonne :

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

Vérifiez également si vous passez dans une chaîne de caractères (s), où un tableau de chaînes de caractères (comme) est nécessaire.


Réf.