systemd-analyze critical-chain 定位真正拖慢开机的关键依赖路径,即从 graphical.target 或 multi-user.target 向上回溯的最长串行阻塞链,其瓶颈在于 @ 时间间隔最大处,而非 + 耗时最长者;输出为缩进树状结构,每行含启动时间点(@x.xxxs)、自身耗时(+y.yyys)及依赖关系。

直接用 systemd-analyze critical-chain 就能定位真正拖慢开机的那条依赖路径——它不看“谁自己跑得慢”,而是找出“谁卡在关键链上,让后面一堆服务干等着”。这条链决定了你系统的最短可能启动时间。
理解 critical-chain 的输出结构
命令默认从 graphical.target 或 multi-user.target 开始向上回溯,输出是缩进树状结构,每行含三个关键信息:
- @X.XXXs:该 unit 实际开始启动的时间点(从系统启动起算)
- +Y.YYYs:该 unit 自身启动耗时
- 缩进关系:下级 unit 是上级的直接依赖,必须等它完成才能启动
例如:
graphical.target @18.420s<br> └─multi-user.target @18.420s<br> └─docker.service @12.105s +3.210s<br> └─containerd.service @9.892s +2.210s<br> └─sysinit.target @1.002s
说明 docker 启动要等到 containerd 完成,而 containerd 又卡在 sysinit 阶段某个环节之后才开始——问题根源很可能不在 docker 本身,而在更早的初始化步骤。
聚焦瓶颈节点的判断方法
关键不是找 + 时间最长 的 service,而是找 @ 时间间隔最大 的两个相邻节点。比如:
network-online.target @6.501s└─NetworkManager-wait-online.service @2.199s +4.302s
这里 @ 时间只差 4.3 秒,但它的 + 耗时却占了整段延迟的绝大部分,且它是 network-online.target 的唯一阻塞点——这类服务就是典型瓶颈。常见嫌疑包括:NetworkManager-wait-online.service(等网络超时)systemd-networkd-wait-online.service(尤其在无 DHCP 环境)docker.service 或 kubelet.service(依赖容器运行时就绪)
针对具体服务深入分析
如果怀疑某个服务是源头,可指定它来查它的关键上游:
systemd-analyze critical-chain docker.servicesystemd-analyze critical-chain NetworkManager-wait-online.service
这样能跳过无关分支,直击它被谁卡住、又卡住了谁。注意:该命令只显示当前处于 active 状态的 unit;若某服务因条件不满足(如 ConditionPathExists= 失败)根本没启动,它就不会出现在链中——此时需配合 systemctl list-units --state=inactive 或 journalctl -b | grep "skipping" 排查跳过原因。
结合 blame 和日志交叉验证
critical-chain 告诉你“哪里堵”,blame 告诉你“谁自身慢”:
- 运行
systemd-analyze blame | head -n 10,看前几名是否出现在 critical-chain 中 - 对链上高耗时 unit,用
journalctl -u xxx.service -b查启动日志,确认是配置问题、磁盘延迟,还是等待外部资源(如远程 API、未插网线) - 若发现某 service 总是卡在“Waiting for…”状态,考虑改用异步方式或禁用等待逻辑(如设置
After=network.target替代Wants=network-online.target)
不复杂但容易忽略











