使用DBus在Python中启用和禁用一个systemd服务

即将推出的picockpit-client会对来自前端的删除事件做出反应 通过停用它的服务 (然而,该应用程序将保持安装)。

同样,当你决定再次运行picockpit-client connect时,该服务将被重新启用并自动为你启动。

这可以通过使用 Python DBus接口.

DBus是一个用于与其他应用程序交互的总线系统。应用程序和系统服务在DBus上发布某种接口,你可以使用它。

以下是如何做到这一点的。

停用一项服务。

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

形象

我们打开 系统总线 - 也有一个SessionBus(dbus.SessionBus()),用于与用户会话交互。然而,在这种情况下,我们要访问系统服务。

对经理来说,这些都是 "标准 "调用--为了访问systemd,你需要通过它们。

下一行是我们指示管理器禁用UnitFiles的地方。这里有一些关于这个的说明。

  • 第一个变量是一个字符串数组--即使你只想禁用一个服务,你也要把它作为一个数组传递。
  • 你传入你的服务的名称,包括'.service'部分--比如说 picockpit-client.service
  • 第二个变量是必需的,如果是假的,则在每次启动时禁用(如果是真的,则只在这个运行时禁用)。

这里是DisableUnitFiles的签名,来自于 DBus / systemd / Freedesktop.org的官方文档:

形象

注意,在与DBus接口进行交互时,提供所有的变量是非常重要的。 他们是 不是 可选的,并且 "设置为合理的默认值",因为你可能从许多其他接口/API中使用。

最后,我在网上看到,修改需要通过使用 manager.Reload() (文件中说。可以调用Reload()来重新加载所有单元文件)

启用并启动一个服务。

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

形象

与上述类似,EnableUnitFiles有以下不同。

  • 在字符串数组后面有两个布尔变量,它们需要被传入
  • 第一个布尔变量,如上所述,决定了该服务是否只在这个运行时启用(True)或普遍启用(False)。
  • 第二个布尔变量,有点隐晦地被描述为。"第二个变量控制指向其他单位的符号链接在必要时是否应被替换"。我决定将其设置为 "真"。

下面是文档中的EnableUnitFiles签名。

形象

仔细想想,我选择的 "True "对于其他应用来说可能并不合适("Force "意味着一种对安全的覆盖)。

最后。 重新启动单位 来实际启动该服务。

  • 注意,这需要一个字符串值,而不是一个字符串数组。
  • 第二个值是一个指定模式的字符串。请参考 正式文件 为不同的模式,这是可能的。

这里是RestartUnit的签名。

形象

注意:我没有处理返回值,理想情况下,特别是对于关键的应用,你会想要研究这个问题--请参考 正式文件.

误区

签名不匹配

ERROR:dbus.connection:无法根据签名'asb'设置参数(['picockpit-client.service'],)。:在D-Bus签名中发现的项目比Python参数中的多

如果你得到类似上述的错误,请检查你是否按照文档中的签名要求传递了所有参数。

在这种情况下,我有(错误)。

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

而不是正确的。

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

也要确保检查你是否传入了一个字符串(s),其中一个字符串数组(作为)是必需的。


参考资料