news 2026/8/29 15:00:48

服务器内核崩溃后如何离线还原现场:kdump + crash 工具 5 步完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
服务器内核崩溃后如何离线还原现场:kdump + crash 工具 5 步完整指南

服务器内核崩溃后如何离线还原现场:kdump + crash 工具 5 步完整指南

【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux

生产机内核一崩,现场就没了?kdump 就是为此准备的"黑匣子":它先把崩溃瞬间的内存完整保存下来,再由 crash 工具在事后把 vmcore 转储文件离线加载,逐帧复现崩溃现场,最终定位到肇事函数。本文按一次真实排障的顺序,走完从配置到分析的完整链路。

一次真实宕机:现象、目标与 kdump 的定位

凌晨两点,机器"无声"重启了

凌晨的生产服务器突然失联:业务报超时,监控里只有一个 reboot 事件。机器起来之后,内核日志里没有完整的 oops 堆栈,应用层的 core 文件也没生成——典型的内核级崩溃。你面对的是两个问题:崩溃发生在哪个函数、是什么数据触发的。

没有现场,就没有分析

如果崩溃瞬间的内存没有被保留,后面的一切推断都只是猜测。kdump 的职责就是解决这个问题:系统正常运行时,它先预留一块内存并加载一个"第二内核";一旦触发 panic,系统通过 kexec 切到这个第二内核,由它把第一个内核的内存导出成 /proc/vmcore(ELF 格式的内存快照),落盘后就能交给 crash 工具做"尸检"。所以整个工作只有两段:崩溃时保现场,崩溃后读现场。

搭好环境:最小可运行配置的 3 步

1. 装 crash 工具和带符号的内核

分析机需要两样东西:crash 工具本身,以及一个带调试符号的 vmlinux(发行版里通常是 debuginfo 包)。

# Debian / Ubuntu sudo apt-get install crash linux-image-$(uname -r)-dbgsym # RHEL / CentOS sudo yum install crash kernel-debuginfo

装完你会看到crash命令可用;缺了 vmlinux,后面的符号、函数名全都对不上。

2. 用 crashkernel 参数预留内存

在启动参数里加 crashkernel。除了crashkernel=512M这种固定值写法,还支持按机器内存容量分档,推荐用这种,小机器不多占、大机器留够:

GRUB_CMDLINE_LINUX="crashkernel=1G-4G:192M,4G-:384M"

意思是:内存 1G~4G 的机器预留 192M,4G 以上预留 384M。改完执行grub2-mkconfig -o /boot/grub2/grub.cfg(或 update-grub)并重启,这块内存才会真正生效。

3. 加载崩溃内核并验证

预留只是"盖好仓库",还要把崩溃内核装进预留区。用发行版自带的 kdump 服务可以免手动:sudo systemctl enable --now kdump。重启后做三项检查:

cat /proc/cmdline # 确认 crashkernel= 参数在 ls -l /sys/kernel/kexec_crash_image # 存在即表示崩溃内核已加载 grep -i crash /proc/iomem # 物理内存中出现 CRASH 保留区

三条都通过,说明"仓库建好、货也入库"。想在测试机上主动演练,可以执行echo c > /proc/sysrq-trigger人为触发一次崩溃,验证 vmcore 能否正常落盘。

到这里,整条链路已经可以概括为 5 步:预留内存 → 加载崩溃内核 → 触发转储 → 加载 vmcore → 追堆栈。后文从第 4 步开始。

还原现场:加载 vmcore 到追出堆栈的 4 个标准动作

加载转储:crash + 匹配的 vmlinux

panic 发生后,系统切到崩溃内核,你把 /proc/vmcore 拷下来落盘(kdump 服务一般会代劳,默认放在 /var/crash 下的时间戳目录)。分析机上这样启动:

crash /usr/lib/debug/lib/modules/$(uname -r)/vmlinux /var/crash/*/vmcore

vmlinux 必须与产生 vmcore 的那次内核版本完全一致,否则符号全部错位。进入后你会看到crash>提示符。

第一步看 sys:确认"死因"和版本

crash> sys KERNEL: /usr/lib/debug/lib/modules/6.1.0-9/vmlinux DUMPFILE: /var/crash/10.0.0.5-.../vmcore PANIC: "BUG: unable to handle page fault for address: 0000000000000018" PID: 4321 COMMAND: "myworker" TASK: ffffc90000123450 CPU: 3

一眼拿到三个信息:崩溃时的 panic 信息、崩溃进程的 PID 和名字、内核版本。后续动作基本都围绕 PID 展开。

再看 log,锁定崩溃前最后时刻

crash> log

输出是崩溃时刻的内核环形缓冲,等价于崩溃瞬间的 dmesg。不要从头看,直接翻最后几十行:Oops/BUG 文本、Call Trace、Modules linked in。它和 bt 的堆栈互相印证,能帮你判断是内核代码还是模块代码。

追堆栈:ps → bt → 异常指令

crash> ps | grep myworker # 拿到崩溃任务的地址和状态 crash> bt 4321 # 打印该任务的完整调用栈

bt的输出从当前栈帧往上依次列出每层函数和寄存器,最关键的行是形如[exception RIP: xxx+0x2c]的异常指令——那就是真正踩雷的那条指令。从它出发,往下读函数上下文、往上读调用链,肇事者基本就出来了。

深入一层:反汇编、结构体与内存

crash> dis my_func # 反汇编出错的函数,找到坏指令 crash> struct task_struct 4321 crash> rd ffffc90000123450 32

dis让你看到具体是 mov 还是 call 出了问题;struct查看任意内核结构体的实时内容;rd读任意地址的原始字节。配合源码一起看,基本能把"谁、在哪、访问了什么"还原完整。

对症下药:三类高频崩溃的判读方法

空指针解引用:看 Oops 错误码和寄存器

症状:log 里出现Oops: 0002 [#1] SMP。错误码低位的 2 表示写操作,再结合高低位可判断是内核态还是用户态触发。动作:bt定位异常 RIP →dis看指令操作数 → 对照寄存器值,哪个寄存器是 0 或接近 0,哪个就是空指针。结论:顺着该指针的来源变量回源码,通常能直接看到漏掉的判空。

页错误:先核对错误地址和指令是否对得上

症状:BUG: unable to handle page fault for address: 0x...。动作:把 bt 给出的异常 RIP 交给dis -l(带行号反汇编),确认指令要访问的地址和报告值一致,排除误判;再rd该地址附近区域。结论:地址合法却访问失败,多半是 use-after-free——对象已释放但指针还活着。

内存异常与内存泄漏:用 kmem 说话

症状:page state 报错、refcount 异常,或运行数天后内存只涨不跌。动作:kmem -p <地址>查看对应 page 的引用计数、映射数等状态;kmem -s列出 slab 缓存占用,隔一段时间再采一次做对比,涨得最凶的 cache 就是嫌疑对象;对可疑结构用search在内存里按值查找。结论:单次快照看状态,两次快照看趋势,泄漏方向往往就藏在这里。

顺手的两个小技巧

看到sys输出里 Tainted 带字母,说明有厂商模块或人为因素,优先怀疑对应组件。另外,频繁出现的 WARN 默认不会留现场,测试机可以加上panic_on_warn=1让 WARN 也触发转储,把现场抓回来。

下一步:进阶路径与一套可带走的清单

让 vmcore 更小、让工具更懂布局

vmcore 动辄几十 GB 时,用makedumpfile -d 31只保留内核数据页,能大幅瘦身。crash 之所以能直接读懂转储,是因为 vmcore 里嵌了一段 VMCOREINFO 元信息(页大小、结构体偏移、符号值),想了解它记录了什么,可以查树内文档 Documentation/admin-guide/kdump/vmcoreinfo.rst;GDB 配合 gdbmacros 宏做轻量分析的方法也在同目录的 kdump.rst 里。

把排障动作固化成肌肉记忆

🧩 建议的下一步很具体:挑一台测试机,完整走一遍"预留 crashkernel 内存 → 启动 kdump 服务 → sysrq 触发崩溃 → 用 crash 加载 vmcore 并执行 sys、log、ps、bt"闭环。把这个四命令序列打印出来贴在排障手册里,下次再遇到无声宕机,你只需要从第 4 步接着跑。

结合 kernel/ 源码逐函数核对,比任何教程都更接近真相。觉得这条链路有用的话,收藏本文,关注后续的内核调试系列。

【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/29 14:59:50

LLM辅助教材写作:从初稿生成到质量验证的工程化实践

这次我们要讨论的不是某个新开的图像模型或一键启动包&#xff0c;而是一个偏思辨、但又非常工程化的话题&#xff1a;一位作者写了一本 AI 教材&#xff0c;然后问“AI 多久能做得更好”。这个提问看起来像一篇博客的开场白&#xff0c;但它背后牵扯到 LLM 写作能力评估、教材…

作者头像 李华
网站建设 2026/8/29 14:59:25

连续扩散语言模型与昇腾算力:ELF架构解析及实践指南

最近 AI 圈有两个方向热度很高&#xff1a;一个是 Meta 何恺明团队提出的 ELF——一种利用扩散模型直接生成任意长度的连续语义特征的语言模型&#xff0c;架构简洁到极致&#xff0c;却在同等参数规模下超越了主流自回归模型&#xff1b;另一个是国内 AI 算力生态的快速成熟—…

作者头像 李华
网站建设 2026/8/29 14:55:12

RuView 指南:穿墙感知人在、呼吸与心率

RuView 指南&#xff1a;穿墙感知人在、呼吸与心率 【免费下载链接】RuView π RuView turns commodity WiFi signals into real-time spatial intelligence, vital sign monitoring, and presence detection — all without a single pixel of video. 项目地址: https://git…

作者头像 李华
网站建设 2026/8/29 14:53:58

低功耗MEMS气压传感器LPS22DF:从选型到驱动实现与避坑指南

最近一个便携气象站项目要选气压计&#xff0c;需求卡得比较死&#xff1a;电池供电、持续工作电流必须尽量小、板面积紧张、精度还不能太拉胯。ST 的 LPS22DF 就这样进入了选型清单。它作为一颗 MEMS nano 压力传感器&#xff0c;把压阻式敏感芯体、温度补偿、24 位 ADC、I2C/…

作者头像 李华
网站建设 2026/8/29 14:48:49

华为Atlas 300I Duo停售启示:AI推理卡生命周期与迁移策略

这次我们不聊新框架&#xff0c;也不跑新模型&#xff0c;而是来看一款生命周期非常短的 AI 推理卡&#xff1a;华为 Atlas 300I Duo。它在社区里被讨论最多的问题不是性能&#xff0c;而是“刚适配完就遇到停售”。从产品发布到停售&#xff0c;整个时间线很短&#xff0c;标题…

作者头像 李华