当前位置:首页 > 文章列表 > 文章 > linux > systemd-analyze critical-chain 怎样定位启动慢的依赖

systemd-analyze critical-chain 怎样定位启动慢的依赖

来源:17golang原创 2026-10-14 14:25:01 0浏览 收藏

Linux 启动变慢时,我通常不会先把 systemd-analyze blame 输出里耗时最长的服务逐个禁掉。更稳妥的顺序是:先用 systemd-analyze critical-chain 找到目标启动链上的关键等待,再用 blame、systemctl status 和 journalctl 判断真正需要处理的单元。

关键点在于“慢”有两种:一个单元可能确实初始化很久,也可能只是排在一个更慢的依赖后面。critical-chain 适合回答“谁在这条启动路径上挡住了目标”,blame 更适合回答“哪些单元自身花费的启动时间较多”。

官方地址:https://www.freedesktop.org/software/systemd/

先定位目标和关键链,再解释单元耗时,最后回到状态与日志。只看一个排序列表,容易把并行启动中的正常等待误判成根因。

先确认要排查的启动目标

先看 systemd 给出的启动总览,确认问题发生在系统启动、某个 target,还是某个服务被拉起时。下面的命令只读取状态,不修改 unit 配置。

# 查看本次启动各阶段的总体耗时
systemd-analyze

# 查看默认启动目标,确认系统最终要到达的 target
systemctl get-default

# 列出当前启动目标的依赖,帮助确认服务是否在这条路径上
systemctl list-dependencies multi-user.target --all

如果问题描述是“开机后某个业务迟迟不可用”,目标不一定是 multi-user.target。可以把具体服务作为后续分析对象,例如 app.service。如果问题只发生在图形环境,则应先确认对应的 target,而不是把所有启动单元混在一起看。

读取 critical-chain 找最长等待路径

critical-chain 会把启动过程中影响目标的关键单元链路打印出来。默认观察启动目标,也可以指定一个 unit。输出中的时间标记用于帮助理解单元何时开始、花费多久以及它依赖谁;示例输出的数值只是格式示意。

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

# 只围绕指定服务查看关键依赖链
systemd-analyze critical-chain app.service

# 查看一个 target 的关键链,避免把无关服务纳入判断
systemd-analyze critical-chain multi-user.target
systemd 启动目标沿关键依赖链回溯等待位置的原创结构说明图
图1:systemd 启动目标沿关键依赖链回溯等待位置的结构说明图。

阅读时先从底部或目标单元开始向依赖方向回溯,找出最长的连续等待段。假设一条链是 multi-user.target 依赖 app.service,而 app.service 又等待网络初始化,那么应该先检查网络相关 unit 是否真的阻塞了目标;不能只因为另一个服务在 blame 里耗时更高,就直接把它当成根因。

用 blame 分辨单元自身耗时

关键链解决的是“影响目标的依赖路径”,但它不等于所有单元的完整耗时排行。接着看 blame,把在启动阶段花费时间较多的单元列出来,与关键链中的候选交叉比较。

# 按启动耗时查看单元,便于找出需要深入检查的候选
systemd-analyze blame

# 输出更适合脚本或表格处理的单元耗时列表
systemd-analyze blame --no-pager

# 查看启动耗时统计和关键链,保留目标上下文
systemd-analyze time
systemd-analyze critical-chain app.service

这里要注意两个边界。第一,systemd 会并行启动很多单元,某个单元耗时较长,不代表它一直阻塞了最终目标。第二,关键链上的短单元也可能很重要,因为它位于连续等待路径中。排障时可以做一个小表格:

观察结果优先判断下一步
critical-chain 上出现并且 blame 也很慢可能是依赖链中的自身初始化瓶颈查看 status 与本次启动日志
critical-chain 上出现但 blame 很短可能是它等待了更早的依赖继续向依赖方向回溯
blame 很慢但不在目标关键链可能没有影响当前目标确认它是否是另一个工作流的问题
输出显示失败、重试或超时迹象启动异常而非单纯性能问题转到 unit 状态和 journalctl

用 status 看单元到底卡在哪里

确定候选后,不要马上编辑 unit 文件。先查看状态、最近一次启动时间和 systemd 记录的结果。下面的 --no-pager 让输出更适合保存到排障记录中。

# 查看服务的当前状态、主进程和最近几行日志
systemctl status app.service --no-pager

# 查看 unit 的完整属性,重点关注启动状态和依赖相关字段
systemctl show app.service \
  -p ActiveState \
  -p SubState \
  -p Result \
  -p ExecMainStartTimestamp \
  -p After \
  -p Requires

status 适合快速判断“服务是否成功、是否正在重启、主进程是谁”;show 适合提取结构化字段。若 Result 表明启动失败或超时,应先修复失败条件,再讨论启动耗时,否则重复重启本身就会污染观察结果。

用 journalctl 对齐本次启动日志

关键链给出路径,状态命令给出当前结果,日志则用来解释为什么等待。排查启动问题时最好限定到一次 boot,避免旧日志把判断带偏。

# 查看本次启动中指定服务的日志,并按时间顺序输出
journalctl -b -u app.service --no-pager --output=short-monotonic

# 只看本次启动的警告及更高等级,减少无关输出
journalctl -b -u app.service -p warning..emerg --no-pager

# 同时观察依赖服务,确认到底是等待、失败还是重试
journalctl -b -u network-online.target -u app.service \
  --no-pager --output=short-monotonic

-b 把范围限定在当前启动批次,-u 按 unit 过滤,--output=short-monotonic 便于比较相对时间。日志中如果出现连接重试、挂载等待、权限错误或超时,应把它们和 critical-chain 中对应的等待位置对齐,而不是只摘一条最醒目的错误。

结合 critical-chain、blame、status 和 journalctl 定位 Linux 启动慢依赖的原创流程说明图
图2:从启动总览到依赖等待、单元耗时和日志定位的排障流程说明图。

修改 unit 前保留可回滚的基线

如果确认是某个依赖关系或初始化动作造成等待,先保存修改前的证据:启动总览、目标关键链、候选单元的 status 和对应 boot 日志。这样调整后才能比较是否真的缩短了目标路径。

# 建立本次排障目录,保存的是诊断结果而不是敏感凭据
mkdir -p /tmp/systemd-boot-check

# 记录目标的关键链与耗时排行,便于修改前后对照
systemd-analyze critical-chain multi-user.target \
  > /tmp/systemd-boot-check/critical-chain.before.txt
systemd-analyze blame --no-pager \
  > /tmp/systemd-boot-check/blame.before.txt

# 记录当前 unit 配置摘要,便于回滚或审阅差异
systemctl cat app.service \
  > /tmp/systemd-boot-check/app.service.before.txt

真正修改时尽量使用 drop-in,而不是直接覆盖发行版提供的 unit 文件。修改后先执行配置重新加载,再单独验证目标服务;如果依赖关系变更扩大了启动范围,应立即恢复原配置并重新采集一次关键链。

# 让 systemd 重新读取 unit 文件,不会自动启动所有服务
systemctl daemon-reload

# 只验证目标服务的状态,避免把排障动作扩大到整台主机
systemctl restart app.service
systemctl status app.service --no-pager

常见误判和一个简短的排查顺序

  1. 把 blame 第一名当成根因:先回到目标的 critical-chain,确认它是否真的位于阻塞路径。
  2. 把链上的每个等待都归咎于最后一个服务:沿依赖方向检查 After=、Requires= 与实际日志。
  3. 混用不同启动批次的日志:优先使用 journalctl -b,必要时明确指定历史 boot。
  4. 没有保留修改前结果就调整多个 unit:一次只改一个影响点,保留 before/after 文件。

我自己实际排这类问题时,会把顺序压缩成四步:systemd-analyze 看总览,critical-chain TARGET 看路径,blame 看候选耗时,最后用 status 和 journalctl -b 解释原因。这样做的好处是先处理真正影响目标的依赖,而不是被一张看起来很长的耗时列表牵着走。

相关问题

critical-chain 和 blame 有什么区别?

critical-chain 关注某个启动目标依赖链上的关键路径;blame 关注单元自身记录的启动耗时排序。两者应该交叉使用,不能互相替代。

为什么 blame 最慢的服务不一定拖慢开机?

systemd 支持并行启动。一个服务即使自身初始化时间较长,只要不在当前目标的关键依赖链上,就可能没有影响目标到达时间。

critical-chain 应该指定服务还是 target?

如果问题是系统进入某个阶段慢,指定相关 target;如果只有一个服务不可用或启动慢,指定该 service,更容易缩小依赖范围。

修改 unit 后看不到变化怎么办?

先确认 drop-in 的位置和内容,再执行 systemctl daemon-reload。随后重新启动目标单元并用新的 boot 日志或状态记录对照,避免把旧输出当成新结果。

总结

systemd-analyze critical-chain 最适合做第一轮路径定位:它帮助你知道哪些依赖连续地影响目标。systemd-analyze blame 用来补充单元自身耗时,systemctl status 和 journalctl -b 则负责把候选连接到状态和日志证据。按这个顺序排查,通常能更快区分“依赖在等什么”和“服务自己做了什么”,也能在修改前后留下可回滚的依据。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
systemd 服务怎样用 Type=notify 表达就绪状态systemd 服务怎样用 Type=notify 表达就绪状态
上一篇
systemd 服务怎样用 Type=notify 表达就绪状态
Linux fanotify 权限事件的允许与拒绝处理方案
下一篇
Linux fanotify 权限事件的允许与拒绝处理方案
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    471次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    530次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    549次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    499次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    317次使用