如何通过DBus即时获取systemd服务崩溃的通知?
我有一个由多个进程组成的Linux应用,其中包含一个「监控进程」,负责在其他进程崩溃时执行相应处理操作。应用内所有进程都注册为systemd服务,目前监控进程通过DBus订阅每个服务的属性,监听ActiveState属性,当该属性变为failed时触发崩溃处理逻辑。
这种方式基本能用,但存在时序问题:进程崩溃时会生成coredump(在ARM系统上最多需要30秒),而ActiveState属性要等到coredump完全完成后才会变更,导致崩溃通知严重延迟。
如何通过DBus即时获取带有服务名的崩溃事件通知?
我已经尝试过以下操作:
- 检查了Service和Unit接口的所有其他属性,崩溃发生时没有任何属性变更
- 检查了systemd
Manager对象的属性,均与该问题无关 - 订阅了
Manager对象的UnitNew信号,能收到coredump服务启动的通知,但无法从coredump服务的属性中明确得知是哪个服务崩溃了
需求:希望继续通过systemd(基于DBus)获取信息,优先采用通知而非轮询的方式。
1. 监听UnitStateChanged信号追踪SubState变化
systemd的org.freedesktop.systemd1.Manager接口提供UnitStateChanged信号,会在单元的任意状态属性变更时触发,包括SubState。当进程崩溃开始生成coredump时,服务的SubState会从running切换为terminating,这个变更远早于ActiveState变为failed的时间。订阅该信号后,解析信号中的单元名(即服务名)和新的SubState值,一旦检测到terminating状态,即可判定对应服务的进程已崩溃,提前触发处理逻辑。
2. 利用JobNew信号捕获服务终止事件
进程崩溃时,systemd会立即创建终止作业(Job)处理该服务。org.freedesktop.systemd1.Manager的JobNew信号会在作业创建时触发,信号包含作业ID、作业类型(如stop)以及关联单元名(服务名)。订阅该信号后,当作业类型为stop且关联单元属于你的目标服务时,即可将其视为崩溃事件的早期通知。
3. 调整systemd配置加速ActiveState变更
如果允许修改服务的systemd配置,可以通过以下方式让ActiveState更快变为failed:
- 设置服务的
KillMode=mixed:systemd会先向主进程发送终止信号,同时立即将服务标记为deactivating,无需等待coredump完成。 - 优化coredump处理:修改
/etc/systemd/coredump.conf,比如设置Storage=none(不需要保留coredump时)或调整ProcessSizeMax限制coredump大小,减少处理时间,从而加快ActiveState的更新。但此方法会牺牲coredump完整性,需根据需求权衡。
4. 解析coredump服务的元数据
你之前通过UnitNew信号能收到coredump服务启动通知,可进一步查询该服务的org.freedesktop.systemd1.Service接口的ExecStart属性,解析其中的命令行参数——coredump服务的启动参数通常包含--unit=字段,对应崩溃的服务名。通过提取该参数值,就能关联到具体崩溃的服务。
内容的提问来源于stack exchange,提问作者Gyorgy Szekely

