排查 systemd 依赖死锁需先用 systemctl list-dependencies --reverse 定位隐性阻塞依赖,再通过 systemctl list-jobs 和 systemctl is-system-running 观察激活卡点,结合 journalctl -u -f 实时日志与 set-log-level debug 暴露调度循环或排队僵局。

排查 systemd 服务因依赖死锁无法启动,核心是识别“循环依赖”或“上游卡住却未报错”的假性正常状态。systemd 不会直接提示“死锁”,而是表现为服务长期处于 activating、deactivating 或反复重启,journalctl 日志空白或只有启动前缀,且 systemctl status 看似无报错但 never 进入 active (running)。
查依赖图谱,定位隐性阻塞点
运行:
systemctl list-dependencies --reverse your-service.service
看它依赖哪些 unit(如 network.target、postgresql.service、remote-fs.target)。再逐个检查这些依赖的状态:
systemctl status 依赖名
重点关注是否为 activating(而非 failed)——这表示它自己也在等别人,形成等待链。
抓启动全过程,发现卡在哪个环节
不要只看最终状态,要观察启动瞬间行为:
sudo systemctl start your-service.service && sudo journalctl -u your-service.service -f
同时开另一个终端执行:
systemctl list-jobs --no-pager
若看到类似 start your-service.service 长时间停留在 running 状态,说明 systemd 正在等某个依赖就绪,但它没发出“ready”信号。
检查关键 target 单元是否真正就绪
很多死锁源于基础 target 卡住,例如:
– network.target:实际网络没通,但 systemd 认为它已“就绪”(因配置了 Wants=network-online.target 却没真正 online)
– remote-fs.target:NFS/CIFS 挂载超时,但 systemd 默认不中断,持续等待
– cryptsetup.target:LUKS 解密失败或密码错误,卡在输入提示(无 TTY 时静默挂起)
验证方法:
systemctl is-system-running —— 若返回 starting 而非 running,说明至少一个关键 target 未完成
绕过依赖,手动验证服务本体是否可运行
临时移除依赖声明,测试服务能否独立启动:
systemctl cat your-service.service | grep -E '^(After|Requires|Wants)='
复制 ExecStart 行,切换到对应 User,手动执行:
sudo -u www-data /usr/local/bin/myapp --config /etc/myapp/conf.yaml
若此时报错(如连接数据库超时、读取配置失败),说明问题不在依赖,而在服务自身初始化逻辑;若成功,则确认是依赖链阻塞。
启用 debug 日志,暴露调度细节
让 systemd 显式打印依赖解析过程:
sudo systemctl set-log-level debug
sudo systemctl restart your-service.service
然后:
journalctl -u your-service.service -n 100 --no-pager | grep -i "dependency\|order\|start"
你会看到类似 Found ordering cycle: A → B → C → A 的提示(若有真循环),或大量 Job for X is already queued(表明调度器陷入重试僵局)。


















