如何在 dbus 回调函数中获取 systemd 服务信息
Posted
技术标签:
【中文标题】如何在 dbus 回调函数中获取 systemd 服务信息【英文标题】:How to get systemd service information inside dbus callback function 【发布时间】:2020-06-23 20:34:58 【问题描述】:我有以下 python 脚本来监控来自所有 systemd 服务的“PropertiesChanged”信号。
#!/usr/bin/env python
import sys
import dbus
import traceback
import dbus.mainloop.glib
from gi.repository import GLib
def catchall_signal_handler(*args, **kwargs):
bus = dbus.SystemBus()
if args:
print(args[0])
print(args[1])
if kwargs:
print(kwargs["path"])
#systemd = bus.get_object('org.freedesktop.systemd1', kwargs["path"])
#manager = dbus.Interface(systemd, dbus_interface='org.freedesktop.systemd1.Manager')
if __name__ == '__main__':
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus()
try:
systemd_proxy_obj = bus.get_object("org.freedesktop.systemd1", "/org/freedesktop/systemd1")
except dbus.DBusException:
traceback.print_exc()
print(usage)
sys.exit(1)
bus.add_signal_receiver(catchall_signal_handler, \
dbus_interface="org.freedesktop.DBus.Properties", signal_name="PropertiesChanged",\
sender_keyword='sender', \
path_keyword='path', \
interface_keyword='interface')
loop = GLib.MainLoop()
loop.run()
我能够获得如下信息。
org.freedesktop.systemd1.Unit
dbus.Dictionary(dbus.String('ActiveState'): dbus.String('activating', variant_level=1), dbus.String('SubState'): dbus.String('auto-restart', variant_level=1), dbus.String('StateChangeTimestamp'): dbus.UInt64(1583953715755499, variant_level=1), dbus.String('StateChangeTimestampMonotonic'): dbus.UInt64(207876008581, variant_level=1), dbus.String('InactiveExitTimestamp'): dbus.UInt64(1583953715755499, variant_level=1), dbus.String('InactiveExitTimestampMonotonic'): dbus.UInt64(207876008581, variant_level=1), dbus.String('ActiveEnterTimestamp'): dbus.UInt64(1583953704417956, variant_level=1), dbus.String('ActiveEnterTimestampMonotonic'): dbus.UInt64(207864671038, variant_level=1), dbus.String('ActiveExitTimestamp'): dbus.UInt64(1583953715754514, variant_level=1), dbus.String('ActiveExitTimestampMonotonic'): dbus.UInt64(207876007596, variant_level=1), dbus.String('InactiveEnterTimestamp'): dbus.UInt64(1583953715754514, variant_level=1), dbus.String('InactiveEnterTimestampMonotonic'): dbus.UInt64(207876007596, variant_level=1), dbus.String('Job'): dbus.Struct((dbus.UInt32(0), dbus.ObjectPath('/')), signature=None, variant_level=1), dbus.String('ConditionResult'): dbus.Boolean(True, variant_level=1), dbus.String('AssertResult'): dbus.Boolean(True, variant_level=1), dbus.String('ConditionTimestamp'): dbus.UInt64(1583953704415513, variant_level=1), dbus.String('ConditionTimestampMonotonic'): dbus.UInt64(207864668599, variant_level=1), dbus.String('AssertTimestamp'): dbus.UInt64(1583953704415517, variant_level=1), dbus.String('AssertTimestampMonotonic'): dbus.UInt64(207864668600, variant_level=1), dbus.String('InvocationID'): dbus.Array([dbus.Byte(134), dbus.Byte(157), dbus.Byte(36), dbus.Byte(192), dbus.Byte(223), dbus.Byte(108), dbus.Byte(77), dbus.Byte(86), dbus.Byte(174), dbus.Byte(132), dbus.Byte(254), dbus.Byte(35), dbus.Byte(71), dbus.Byte(91), dbus.Byte(246), dbus.Byte(215)], signature=dbus.Signature('y'), variant_level=1), signature=dbus.Signature('sv'))
/org/freedesktop/systemd1/unit/tftp_2eservice
在 catchall_signal_handler() 函数中,现在我想获取服务名称,即 (tftp.service)
获取此信息的正确方法是什么?
我是 dbus API 编程的新手。
试过这个(How to extract service state via Systemd DBus API?)但没有帮助。 请提供一些有用的提示/指针。
我的最终目标是监控一组预定义的服务。 例如:[“tftp.service”、“docker.service”、“kubernetes.service”]
上述方法是否正确?请建议。
【问题讨论】:
你不能使用kwargs["path"]
来过滤'tftp_2eservice'
吗?
@stovfl 是的,这是解析路径的一种方法。我正在寻找一个 API 来检索相同的
“寻找一个 API 来检索相同的”:为什么?您可以使用.get_object(kwargs['path'], ...
获得ProxyObject
,但这与object_path
相同。您的服务列表["tftp.service", "docker.service", "kubernetes.service"]
似乎是.service
文件名的列表。这些名称不等于 path
名称。
好的,知道了。我在下面尝试过,我能够获得服务名称。 service_proxy = bus.get_object("org.freedesktop.systemd1", "/org/freedesktop/systemd1/unit/tftp_2eservice" ) service_properties = dbus.Interface(service_proxy, dbus_interface="org.freedesktop.DBus.Properties") name = service_properties.Get("org.freedesktop.systemd1.Unit", 'Id')
【参考方案1】:
使用以下 API 调用,我能够获取服务名称。
def catchall_signal_handler(*args, **kwargs):
bus = dbus.SystemBus()
if args:
print(args[0])
print(args[1])
if kwargs:
print(kwargs["path"])
service_proxy = bus.get_object('org.freedesktop.systemd1', kwargs["path"])
service_properties = dbus.Interface(service_proxy, dbus_interface="org.freedesktop.DBus.Properties")
name = service_properties.Get("org.freedesktop.systemd1.Unit", 'Id')
print(name)
【讨论】:
我在.Get("org.freedesktop.systemd1.Unit", 'Id')
得到ValueError: Invalid object path ... does not start with '/'
@stovfl 它适用于我的系统。 [root@sandeep-fedora ~]#python Python 2.7.15 (default, Oct 15 2018, 15:26:09) [GCC 8.2.1 20180801 (Red Hat 8.2.1-2)] on linux2 >>> import dbus >>> bus = dbus.SystemBus() >>> service_proxy = bus.get_object('org.freedesktop.systemd1', "/org/freedesktop/systemd1/unit/rsyslog_2eservice") >>> service_properties = dbus.Interface(service_proxy, dbus_interface="org.freedesktop.DBus.Properties") >>> name = service_properties.Get("org.freedesktop.systemd1.Unit", 'Id') >>> str(name) 'rsyslog.service'
我使用的是 Python 3.x,Debian。还有,没有在freedesktop - dbus 中找到.Get(...
方法。也许不同的dbus
模块?以上是关于如何在 dbus 回调函数中获取 systemd 服务信息的主要内容,如果未能解决你的问题,请参考以下文章
通过 python 和 dbus 启动用户 systemd 服务
与 SystemD 的 Linux DBus 远程 TCP 连接失败