登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  linux

Linux 怎样用 systemd-analyze 找启动瓶颈

来源:17golang原创

时间:2026-10-18 02:11:18 123浏览 收藏

Linux 启动变慢时,最容易走偏的一步,是看到 systemd-analyze blame 排名第一就立刻禁用那个服务。更稳妥的判断顺序是:先确认慢在 kernel、initrd 还是 userspace,再用 blame 找候选,最后用 critical-chain 判断它是否真的挡住了目标 target。

官方地址:https://systemd.io/DEBUGGING/

一句话结论:blame 回答“哪些单元启动时花的时间多”,critical-chain 回答“哪些依赖关系实际位于目标启动的关键路径上”。两份输出要结合阅读,不能互相替代。

先确认启动慢在哪一段

先看总账,不要马上钻进某个服务。systemd-analyze time 会把启动过程按 kernel、initrd 和 userspace 等阶段呈现出来,同时给出目标到达 userspace 后的时间。这个结果适合回答“问题属于哪个阶段”,不适合直接指出某个服务的根因。

# 先看内核、initrd 和用户空间各阶段的耗时
systemd-analyze time

# 记录当前默认目标对应的关键依赖链,便于后续对照
systemd-analyze critical-chain

如果主要时间出现在 kernel 或 initrd,继续只看 systemd unit 排名往往没有收益;如果 userspace 占比明显,再进入服务单元分析。这个分流会让后面的判断范围更小。

kernel、initrd、userspace、multi-user.target 与 systemd-analyze time 的静态关系图
图1:启动阶段与 systemd-analyze time 观察结果的静态关系;这是说明图,不是运行截图。

用 blame 找值得解释的候选单元

确认慢在 userspace 后,再执行:

# 按单元初始化耗时从高到低列出正在运行的单元
systemd-analyze blame

这份列表适合做“候选发现”。排名靠前的单元可能自身初始化较慢,也可能只是等待了别的依赖;因此,排名只能说明它在启动统计中显眼,不能单独证明它拖慢了最终目标。

还要记住两个边界:第一,blame 观察的是进入 activating 状态的启动耗时,像某些直接从 inactive 变为 active 的设备单元不一定能被同样方式反映;第二,Type=simple 服务会被 systemd 视为立即启动,因此这里看不到可比的初始化延迟。不要把“列表里没有”解读成“这个服务没有影响”。

用 critical-chain 确认真正的阻塞关系

如果目标是判断“谁让默认目标晚到”,关键命令是:

# 查看默认目标的时间关键链
systemd-analyze critical-chain

# 也可以围绕一个明确的 unit 查看它的关键链
systemd-analyze critical-chain network-online.target

critical-chain 输出的是一棵面向目标 unit 的时间关键依赖树。它更接近“启动完成被哪条依赖关系卡住”,而不是“所有单元谁最慢”。例如,一个服务自身启动用了几秒,但它与其它服务并行启动,可能并不延后目标;另一个服务只用了几百毫秒,却可能位于目标唯一的串行依赖上,反而更值得优先解释。

因此,排查可以采用一个简单决策:先从 blame 取出候选,再看候选是否出现在目标的关键链上;不在关键链上的慢单元先保留记录,不急着改配置。

blame 排名与 critical-chain 依赖树的静态对比图
图2:blame 与 critical-chain 的问题分工及关键字段;这是结构图,不代表某台机器的实际输出。

读懂输出里的 @ 和 +

关键链中的单元通常会带有类似 unit.service @12.300s +1.200s 的信息。可以按两个维度读:

  • @ 后面表示该单元进入 active 或被启动时的时间点,它帮助你把单元放回整条启动时间线上。
  • + 后面表示该单元自身花费的启动时间,适合和同一链上的前后节点比较。

不要把两个数字相加后当成整机启动时间。关键链只是依赖关系的一条时间解释路径,启动过程中仍可能有大量单元并行执行;同时,设备单元和超时任务也可能不完全落入相同的 activating 统计口径。

按接口目标推进下一步排查

把三个命令看成三个接口,职责会更清楚:

命令它回答的问题下一步
systemd-analyze time慢在启动的哪个大阶段决定是否进入 userspace 排查
systemd-analyze blame哪些运行单元初始化时间显眼建立候选清单
systemd-analyze critical-chain哪些依赖实际位于目标关键路径缩小到需要解释的节点

对关键链上仍然可疑的节点,再查看状态和本次启动日志:

# 查看单元当前状态、最近日志摘要和失败原因
systemctl status example.service

# 只查看本次启动中该单元的日志,避免混入旧启动记录
journalctl -b -u example.service

这里的 example.service 只是占位符,应替换为关键链中真实出现的 unit。若日志显示的是依赖等待、设备出现或网络就绪超时,问题方向与“服务程序自身初始化慢”不同,后续处理也不能套用同一方案。

常见误判

只看 blame 第一名就禁用服务

错误在于把候选排序当成因果链。先确认它是否位于目标的 critical chain,再结合状态和本次启动日志判断。

把 critical-chain 当成完整启动拓扑图

关键链是面向目标的时间路径,不是所有依赖和并行任务的完整展开。想了解全局关系时,需要另外选择依赖分析工具,但本文的启动瓶颈判断仍以阶段、候选和关键链三层为主。

看到 unit 不在 blame 就认为它没有问题

不同类型的 unit、socket 激活、设备状态和排队等待会影响统计表现。缺少排名信息时,应回到目标链、状态和日志,不要用空缺字段做结论。

总结

用 systemd-analyze time 做阶段分流,用 blame 发现候选,用 critical-chain 确认影响目标的依赖关系,再用 systemctl status 和 journalctl -b -u 补充证据。这个顺序的价值不在于一次命令就给出答案,而在于把“看起来慢”逐步收敛成“哪一段、哪个候选、是否真的挡在关键路径上”。

相关问题

systemd-analyze blame 能直接说明哪个服务拖慢了开机吗?

不能。它提供初始化耗时排序,仍需结合关键链和并行关系判断是否影响目标到达。

critical-chain 后面的加号是什么意思?

加号后的时间表示该 unit 自身的启动耗时;@ 后的时间表示它在启动时间线上的激活时刻。

为什么设备单元在 blame 里不明显?

设备类 unit 可能直接从 inactive 变为 active,没有经历可按 activating 状态统计的启动阶段。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>