Kernel Panic 是 Linux 最严重的故障之一。它意味着内核遇到了无法继续运行的致命错误,只能停下来——表现通常是一屏滚动的堆栈信息,然后服务器失去响应、SSH 断开、业务全停,有些情况下还会打印一串十六进制数字后自动重启。对物理机运维来说,看到 Kernel Panic 往往伴随着"半夜被叫醒"和"上网本连不上"。
很多人对 Kernel Panic 有一种无力感:错误信息看不懂,机器又不响应,只能重启。这篇文章要把它拆开讲清楚:Kernel Panic 是怎么发生的(为什么内核选择"停下来"而不是继续跑)、最常见的诱因有哪些、在没有屏幕的服务器上怎么拿到崩溃现场(IPMI、串口、kdump 的 vmcore)、有了 vmcore 之后怎么用工具分析出"是谁的锅",以及怎么恢复和预防。读完你应该知道:Panic 并不可怕,可怕的是它发生时你没有任何日志。 做好 kdump 和串口日志,绝大多数 Panic 都能定位到具体原因。
一、Kernel Panic 是什么,为什么会发生
内核是整个系统的底层核心,管理内存、进程、设备、文件系统。正常运行时,内核代码对访问的内存、硬件状态有严格假设。当某个假设被打破——比如内核访问了一段非法内存、遇到了硬件报告的不可恢复错误、或者检测到内部数据结构已经损坏——继续运行下去可能会导致更严重的数据损坏。这时内核的自我保护机制就是:打印诊断信息(oops/panic),然后停止,宁可停机也不带着错误往下跑。
几个相关概念要分清:
- Oops:内核发现了错误,杀掉了当前进程,但系统还能继续运行。日志里会有
Oops:、调用栈(call trace)。 - Panic:错误严重到内核无法继续,调用
panic(),系统停止或重启。Oops 也可能升级为 Panic(取决于panic_on_oops)。 - MCE(Machine Check Exception):CPU 检测到硬件级错误(内存、缓存、总线),严重时直接触发 Panic。
- BUG / soft lockup / hard lockup:内核自检发现逻辑错误或 CPU 长时间卡住,也可能导致 Panic。
一句话总结:Panic 是内核"投降"了,并且通常会留下现场——前提是你配置好了日志和 kdump。
二、Kernel Panic 的常见诱因
按出问题概率,Panic 的诱因大致可以分为这几类:
| 诱因 | 典型表现 | 常见日志关键字 |
|---|---|---|
| 硬件内存故障 | MCE、ECC 不可纠正错误 | Machine Check、MCE、EDAC |
| 驱动/内核模块 bug | Oops 调用栈里有模块名 | Oops、RIP:、模块名 |
| 内核自身 bug | 特定操作后必现 | BUG:、kernel BUG at |
| 文件系统/磁盘损坏 | 读写特定文件时崩溃 | EXT4-fs error、XFS、JBD2 |
| 过热/电源 | 与负载、时间相关 | thermal、thermal shutdown |
| 热插拔/硬件变动 | 拔插设备、换盘后 | pcie、ACPI、hotplug |
| 第三方闭源驱动 | 装了非官方驱动后出现 | 驱动模块名 |
| 内核与硬件不兼容 | 新硬件+老内核 | 无明确关键字,需回退内核验证 |
几个值得记的经验规律:
- 装完某个驱动就 Panic:优先怀疑该驱动。用
lsmod看是不是它,尝试卸载或换版本。 - 升级内核后开始 Panic:优先怀疑新内核 bug 或驱动不兼容,回退到旧内核验证(见第五节)。
- 毫无规律、多台机器同时或同型号出现:偏向硬件或批次性问题。
- 只在特定负载/操作下复现:偏向软件 bug(内核或驱动)。
内存故障是最容易被忽略的一类
很多"神秘 Panic"最后都指向内存。ECC 不可纠正错误(UE)会被 CPU 报告为 MCE,直接触发 Panic。
# 看是否有 EDAC 内存报告
dmesg -T | grep -iE 'edac|mce|machine check|correctable|uncorrectable'
# mcelog 工具
sudo yum install -y mcelog
mcelog --client 2>/dev/null || cat /var/log/mcelog
# 一些主板/云环境的硬件错误日志
journalctl -b -1 -k --no-pager | grep -iE 'mce|machine check|hardware error'
如果确认是内存故障,处理方式是:跑内存测试(如 memtest86+)定位坏条、更换内存条、调整 ECC 策略(仅在极端情况下才考虑,会牺牲可靠性,不推荐)。
三、拿到崩溃现场:几种手段
Panic 发生时机器已经不响应了,怎么把日志拿到手?有这么几条路。
1. 本地控制台 / 显示屏
如果有显示器或 KVM,最直接:屏幕上的信息就是第一现场。用手机拍照,重点拍调用栈和 RIP: 那一行以及模块名。
2. 带外管理(IPMI / iDRAC / iLO)
绝大多数服务器有带外管理。它可以远程看到控制台画面、远程控制电源,并且有独立的事件日志(SEL)。
# 通用 IPMI 工具
sudo yum install -y ipmitool
sudo apt install -y ipmitool
ipmitool -I lanplus -H -U -P sel list # 系统事件日志
ipmitool -I lanplus -H -U -P sel elist # 带时间的事件
ipmitool -I lanplus -H -U -P chassis power status
带外控制台一个极其重要的用途是:看清 Panic 屏幕并操作 GRUB。物理机 Panic 后无法通过 SSH 进,只能靠带外控制台来选旧内核或进救援模式。
3. 串口控制台(Serial Console)
配置内核把日志输出到串口,用另一台机器或带外管理抓取,可以在系统完全卡死时仍然保存 Panic 输出。
# 修改内核启动参数,加串口控制台(GRUB)
# 编辑 /etc/default/grub,在 GRUB_CMDLINE_LINUX 里追加:
# console=tty0 console=ttyS0,115200n8
sudo grub2-mkconfig -o /boot/grub2/grub.cfg # RHEL/CentOS/Rocky (BIOS)
sudo update-grub # Debian/Ubuntu
# 之后用 minicom / screen 连接串口抓取
4. kdump:最关键的持久化现场
kdump 是 Linux 的标准机制:预先保留一小块内存(crashkernel),当系统 Panic 时,内核会启动一个"转储内核(kexec)",把崩溃内核的完整内存镜像(vmcore)写到磁盘(通常是 /var/crash/)。这个 vmcore 就是事后分析的"黑匣子"。
配置 kdump:
# 安装
sudo yum install -y kexec-tools # RHEL/CentOS/Rocky
sudo apt install -y kdump-tools crash # Debian/Ubuntu
# 确认内核预留了 crashkernel 内存
grep -o 'crashkernel=[^ ]*' /proc/cmdline
# 若没有,编辑 GRUB 加 crashkernel=auto 或 crashkernel=512M,再 grub 更新并重启
# /etc/default/grub: GRUB_CMDLINE_LINUX="... crashkernel=512M"
# 启用 kdump
sudo systemctl enable --now kdump
sudo systemctl status kdump
# 预留是否生效,看这个文件末尾
cat /sys/kernel/kexec_crash_loaded # 应为 1
# 配置保存路径和大小(按内存大小给够,一般自动)
grep -E 'path|core_collector' /etc/kdump.conf
风险提示:修改 crashkernel 需要重启,且会占用一部分内存(一般 512M~1G 量级,视机器)。改动前确认业务可重启窗口,并在带外控制台里操作以防重启失败。
kdump 生效后,每次 Panic 会在 /var/crash/<时间戳>/ 下生成 vmcore 和 vmcore-dmesg.txt。vmcore-dmesg.txt 本身就包含完整的崩溃日志,很多时候看它就能定位。
5. 持久化内核日志
确保 journald 持久化,这样即使普通重启,崩溃前的内核日志也能保留。
sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald
journalctl -k -b -1 --no-pager | tail -100 # 看上次启动的内核日志
四、分析 vmcore:用 crash 工具找出根因
有了 vmcore,就可以用 crash 工具"回到"崩溃那一刻。基本流程:
# 安装 crash 和对应内核的 debuginfo(debuginfo 很重要,否则符号缺失)
sudo yum install -y crash
# RHEL/CentOS 需要 debuginfo 仓库
sudo yum install -y kernel-debuginfo-$(uname -r)
# 启动 crash 加载 vmcore
sudo crash /usr/lib/debug/lib/modules/$(uname -r)/vmlinux /var/crash/<时间戳>/vmcore
进入 crash 交互界面后,常用命令:
crash> bt # 打印崩溃时的调用栈(backtrace),最关键
crash> bt -a # 所有 CPU 的调用栈
crash> log # 内核日志(相当于崩溃时的 dmesg)
crash> sys # 系统信息
crash> ps # 进程列表
crash> kmem -i # 内存使用概况
crash> mod # 已加载模块
crash> dis -l <地址> # 反汇编出错地址,结合符号看是哪行代码
crash> exit
bt 和 log 是最高价值的两条:bt 告诉你内核崩在哪个函数的调用链上,log 给出崩溃前上下文。结合 dis -l 定位到具体指令,往往能看出是哪个模块、哪行代码出了问题。
如果嫌 crash 重,也可以先看最简单的 vmcore-dmesg.txt:
cat /var/crash/<时间戳>/vmcore-dmesg.txt | tail -100
grep -iE 'panic|oops|RIP:|Call Trace|BUG|mce' /var/crash/<时间戳>/vmcore-dmesg.txt
五、恢复:让系统先起来
诊断的同时或之前,得先把业务恢复。
1. 重启
最简单,带外控制台点一次电源循环即可。但如果 Panic 是必现的(每次都崩在同一处),重启后要尽快行动。
2. 回退到旧内核(升级后 Panic 的首选)
如果是升级内核后开始 Panic,在 GRUB 菜单里选择上一个正常的内核启动:
# 查看系统里已安装的内核
rpm -qa | grep '^kernel-' # RHEL 系
dpkg -l | grep linux-image # Debian 系
# 查看默认启动项
grubby --default-kernel # RHEL 系
grub2-editenv list # 或看 grubenv
# 设置默认启动到指定旧内核(RHEL 系,需谨慎)
sudo grubby --set-default /boot/vmlinuz-<旧版本>
# Debian/Ubuntu:GRUB 菜单里选 "Advanced options" 选旧内核启动
# 重建 GRUB 配置
sudo grub2-mkconfig -o /boot/grub2/grub.cfg # RHEL 系 BIOS
sudo update-grub # Debian/Ubuntu
在带外控制台里,重启时按 Esc/Shift 进入 GRUB 菜单,选 "Advanced options for ..." 挑旧内核。这是无 SSH 时唯一的操作入口。
风险提示:grubby --set-default 会改变默认启动项,改错可能导致起不来。改之前记录当前默认值,出问题可 grubby --set-default 切回。操作尽量在带外控制台里做,留一条退路。
3. 救援模式(Rescue)
如果系统根本进不去(文件系统损坏、内核全崩),用安装介质或云控制台的救援模式启动一个最小的系统,挂载原根分区进行修复:
# 救援模式下(进入后一般原系统挂在 /mnt/sysroot)
# 检查并修复文件系统(务必先 umount)
umount /dev/sda2
fsck -y /dev/sda2
# 或 XFS
xfs_repair /dev/sda2
# chroot 进去改配置
mount --bind /dev /mnt/sysroot/dev
chroot /mnt/sysroot
# ...修改配置、改 GRUB 等
风险提示:fsck -y 和 xfs_repair 会对文件系统做修改,可能在损坏盘上造成数据丢失,操作前尽量对盘做镜像或至少备份关键数据。
六、预防:让下次不再抓瞎
Panic 无法完全避免,但可以做到"下次发生时有据可查、快速恢复"。
- 始终开启 kdump 并确认
/var/crash有空间(至少留几 GB)。这是分析 Panic 的根本。 - 开启 journald 持久化,保住普通崩溃前的日志。
- 配置串口/带外控制台日志抓取,物理机尤其重要。
- 用经过时间检验的稳定内核,不要盲目追最新大版本;厂商内核(如 RHEL 系的内核)经过长期测试,稳定性通常优于随手编译的社区版。
- 内存体检:新装机器或怀疑内存时跑 memtest86+;日常监控 ECC 可纠正错误计数,增长就换条。
- 监控温度与硬件事件:用 IPMI 定期巡检 SEL,监控 CPU 温度、风扇转速、电源状态。
- 变更管理:升级内核、装新驱动、改硬件前先做快照/记录,出问题能快速回滚。
- 谨慎对待第三方闭源驱动,它们在 Panic 原因里占比不低。
常见问题
Q:屏幕一闪而过,没看清 Panic 信息怎么办?
配置串口控制台或 kdump。也可以在 GRUB 里加 panic=0(不自动重启,停在屏幕)或 panic=10(10 秒后重启),给自己留时间拍照。加 pause_on_oops 也可让 Oops 停下来。
Q:kdump 没抓到 vmcore,可能是什么原因?
常见原因:没预留 crashkernel 内存;/var/crash 空间不足;kdump 服务没启动或被防火墙/存储影响;崩溃类型太严重(如硬件级 MCE 直接断电)。逐项检查 cat /sys/kernel/kexec_crash_loaded 应为 1。
Q:没有 vmcore,只有一段 dmesg,能分析吗?
可以。vmcore-dmesg.txt 或 /var/log/messages / journalctl -b -1 -k 里的调用栈足够缩小范围。重点看 RIP:、Call Trace、最后加载的模块。
Q:怎么判断是硬件还是软件问题?
有 MCE/EDAC/thermal 等硬件关键字,偏硬件;只有 BUG:、Oops、纯函数调用栈且能稳定复现,偏软件(内核或驱动 bug)。最快的验证是回退内核或卸载可疑驱动,看问题是否消失。
Q:虚拟机里的 Kernel Panic 怎么处理?
虚拟机 Panic 通常和虚拟化平台、虚拟硬件驱动(virtio 等)有关。先看宿主机日志和虚拟化平台事件,再在虚机里看 dmesg;也可以给虚机配置串口日志输出到宿主机文件。
总结
Kernel Panic 是内核遇到不可恢复错误时的自我保护性停机。它不是"无缘无故",而是有具体原因:内存故障、驱动/内核 bug、文件系统损坏、过热等。
诊断的关键是留住现场:kdump(vmcore)最重要,其次是串口/带外控制台日志、journald 持久化。分析用 crash 工具,重点看 bt(调用栈)和 log(内核日志)。
恢复手段包括直接重启、回退旧内核(升级后 Panic 首选)、救援模式修复文件系统。物理机必须依赖带外控制台操作 GRUB。
预防上,开启 kdump 和持久化日志、使用稳定内核、做内存与硬件巡检、规范变更管理,能让下一次 Panic 从"抓瞎"变成"快速定位"。记住:没有日志的 Panic 才是最可怕的,配置好 kdump 是每个生产物理服务器的必修课。
企业QQ咨询




