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 占比明显,再进入服务单元分析。这个分流会让后面的判断范围更小。

用 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 取出候选,再看候选是否出现在目标的关键链上;不在关键链上的慢单元先保留记录,不急着改配置。

读懂输出里的 @ 和 +
关键链中的单元通常会带有类似 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 状态统计的启动阶段。
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
144 收藏
-
121 收藏
-
272 收藏
-
467 收藏
-
228 收藏
-
136 收藏
-
442 收藏
-
279 收藏
-
434 收藏
-
465 收藏
-
文章 · linux | 1小时前 | 服务管理 · Linux systemd systemd.socket ListenStream Accept socket activation systemd.service376 收藏
-
194 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习