ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

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

服务器内核崩溃后如何离线还原现场: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/vmcoreELF 格式的内存快照落盘后就能交给 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。除了crashkernel512M这种固定值写法还支持按机器内存容量分档推荐用这种小机器不多占、大机器留够GRUB_CMDLINE_LINUXcrashkernel1G-4G:192M,4G-:384M意思是内存 1G~4G 的机器预留 192M4G 以上预留 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 匹配的 vmlinuxpanic 发生后系统切到崩溃内核你把 /proc/vmcore 拷下来落盘kdump 服务一般会代劳默认放在 /var/crash 下的时间戳目录。分析机上这样启动crash /usr/lib/debug/lib/modules/$(uname -r)/vmlinux /var/crash/*/vmcorevmlinux 必须与产生 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: xxx0x2c]的异常指令——那就是真正踩雷的那条指令。从它出发往下读函数上下文、往上读调用链肇事者基本就出来了。深入一层反汇编、结构体与内存crash dis my_func # 反汇编出错的函数找到坏指令 crash struct task_struct 4321 crash rd ffffc90000123450 32dis让你看到具体是 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_warn1让 WARN 也触发转储把现场抓回来。下一步进阶路径与一套可带走的清单让 vmcore 更小、让工具更懂布局vmcore 动辄几十 GB 时用makedumpfile -d 31只保留内核数据页能大幅瘦身。crash 之所以能直接读懂转储是因为 vmcore 里嵌了一段 VMCOREINFO 元信息页大小、结构体偏移、符号值想了解它记录了什么可以查树内文档 Documentation/admin-guide/kdump/vmcoreinfo.rstGDB 配合 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),仅供参考
返回列表