使用Python低耗获取Linux服务信息的性能优化咨询
现有代码优化方案
- 减少subprocess额外开销:你当前的写法虽然拼了多个命令,但还是需要经过shell解析,且没有用到systemctl原生支持多服务查询的特性。直接一次传入所有待查询服务名,关闭
shell=True避免额外的shell进程开销,CPU占用会更低:
import subprocess import time # 所有待查询服务统一放到列表中管理 target_services = [ "alsa-restore.service", "apt-daily.service", "cryptdisks-early.service" # 其余待查询服务直接加在列表里即可 ] start_time = time.time() # 一次systemctl调用返回所有服务的查询结果 cmd = ["systemctl", "show", *target_services, "--property=LoadState,UnitFileState,ActiveState,SubState"] output = subprocess.check_output(cmd, shell=False).decode() end_time = time.time() print(end_time - start_time)
- 优化结果解析逻辑:systemctl返回的多服务结果用空行分隔,你可以一次性解析成字典结构存储,对于状态稳定的服务(比如长期处于disabled、dead状态的服务)可以加短时间缓存,不需要每次都全量查询。
更低开销的获取途径
- 直接调用systemd的DBus接口:不需要创建任何子进程,开销比subprocess低3~10倍,完全满足高频调用、低CPU占用的要求。Debian系环境先安装
python3-dbus依赖包即可使用,示例代码如下:
import dbus # 全局复用DBus连接,避免每次查询重建连接的开销 bus = dbus.SystemBus() systemd_obj = bus.get_object('org.freedesktop.systemd1', '/org/freedesktop/systemd1') systemd_manager = dbus.Interface(systemd_obj, 'org.freedesktop.systemd1.Manager') def batch_get_service_state(service_list: list) -> dict: result = {} for service_name in service_list: unit_path = systemd_manager.LoadUnit(service_name) unit_obj = bus.get_object('org.freedesktop.systemd1', unit_path) unit_prop = dbus.Interface(unit_obj, 'org.freedesktop.DBus.Properties') result[service_name] = { "LoadState": str(unit_prop.Get('org.freedesktop.systemd1.Unit', 'LoadState')), "UnitFileState": str(unit_prop.Get('org.freedesktop.systemd1.Unit', 'UnitFileState')), "ActiveState": str(unit_prop.Get('org.freedesktop.systemd1.Unit', 'ActiveState')), "SubState": str(unit_prop.Get('org.freedesktop.systemd1.Unit', 'SubState')) } return result
- 直接读取系统运行时状态文件:如果对性能有极端要求,可以直接读
/run/systemd/units/下的服务状态文件、/sys/fs/cgroup/systemd/下的cgroup状态,不需要依赖任何第三方组件,缺点是需要自己解析文件格式,兼容性比DBus接口差。
额外优化建议
- DBus连接和systemd管理器对象不要每次查询都重新创建,全局复用即可进一步降低开销。
- 如果业务允许毫秒级的延迟,可以给查询结果加1~5秒的缓存,相同查询直接返回缓存内容,不需要每次调用接口。
内容的提问来源于stack exchange,提问作者pythonlearner9001
相关产品推荐
相关产品推荐

