必须用 systemd-analyze blame --all --no-pager 才能查到所有服务真实启动耗时,否则 failed、activating 或被条件跳过的服务会被遗漏;再用 critical-chain 追溯依赖链定位瓶颈。

直接用 systemd-analyze blame 查,但必须加 --all 和 --no-pager,否则你看到的很可能不是它真实的启动耗时。
为什么 systemd-analyze blame 默认不显示你要的服务
默认只列出当前状态为 active 的 service 和 mount 单元。如果你的服务启动失败、卡在 activating (start)、或者被 ConditionPathExists 跳过,它根本不会出现在输出里——你以为它没拖慢启动,其实它才是瓶颈。
常见漏掉的情况包括:
-
dev-disk-by\x2duuid-1234567890abcdef.mount因 USB 拔掉或 NFS 不可达而 failed -
NetworkManager-wait-online.service卡在 DHCP 超时,状态是activating - 自定义 service 因
ExecStart路径错误,根本没跑起来
正确命令是:systemd-analyze blame --all --no-pager | grep "your-service-name"
systemd-analyze critical-chain your-service-name 才知道它到底“卡在哪”
blame 只告诉你“它自己花了多久”,但服务启动慢往往不是它自己慢,而是上游等得久。比如 nginx.service 显示耗时 120ms,但它依赖的 network-online.target 等了 15 秒,那 nginx 就得干等。
运行:systemd-analyze critical-chain nginx.service
你会看到一条从 nginx.service 往上追溯的依赖链,每行末尾的 +X.XXXs 是该单元**自身启动耗时**,不是等待时间。重点看链中最上面那个耗时大的环节,再查它的 blame 或日志。
确认它是否真被 systemd 启动过,别被“状态正常”骗了
有些服务看似 active (running),但 systemd-analyze blame 里完全没它——说明它这次根本没走 systemd 的启动流程,可能是手动启的、被 socket 激活的,或者被 timer 触发的。
验证方法:
- 查 journal:
journalctl -u your-service-name --since "1 hour ago" | head -20,看有没有Starting...日志 - 查 unit 加载状态:
systemctl is-enabled your-service-name(是否设为开机自启) - 查实际启动时间:
systemctl show your-service-name --property=ActiveEnterTimestampMonotonic,返回值是纳秒级启动时刻,可换算成相对 boot 时间
如果 ActiveEnterTimestampMonotonic 是 0,说明它压根没被 systemd 启动过。
真实耗时可能比 blame 显示的高得多
systemd-analyze blame 统计的是从 start 到 running 的 active 时间,不包含:
- 依赖单元未就绪导致的排队等待(比如等
local-fs.target) - I/O 阻塞(如读配置文件卡在 slow disk)
- 内核模块加载延迟(
Type=notify服务等sd_notify前的空档)
想抓这类问题,得结合:systemd-analyze plot > boot.svg 看服务之间有没有大片空白;或者用 journalctl -b | awk '/Started|Starting/ {print $1,$2,$3,$4,$5}' 手动对齐时间戳。
最常被忽略的一点:重启后立刻跑 blame,结果受上次残留状态干扰。真正诊断前,先 sudo systemctl reboot,等系统冷启动完成再查。


















