dmesg是Linux内核环形缓冲区的查看工具,用于排查硬件故障、驱动异常和系统崩溃,需结合时间戳、日志级别和关键词三重过滤,并配合其他工具交叉验证。

首先要确定到底是“系统失联”还是“真崩溃”——许多所谓的崩溃其实只是sshd挂了、防火墙封了或者网络中断,根本没到内核层面。只有看到控制台输出了 Kernel panic、Oops、Out of memory: Kill process这类字样,才算是进入了崩溃分析环节。
看 dmesg 输出里最靠近 panic 的那几行
内核环形缓冲区(ring buffer)里保留着崩溃前最后的线索,但默认 dmesg 输出太杂,关键信息被淹没:
- 必须加
-T显示可读时间戳,否则无法对齐其他日志 - 用
grep -A 20 -B 5 -E "(Kernel panic|Oops|BUG:|Call Trace:)"抽出上下文:-B 5 往上抓前兆(比如连续的 I/O timeout),-A 20 往下取完整调用栈 - 如果系统已重启,
dmesg只剩新启动日志,此时要查/var/log/kern.log.1.gz:zcat /var/log/kern.log.1.gz | grep -A 20 -B 5 "Kernel panic" - 别依赖
journalctl -b -1 | grep panic—— journal 在 panic 瞬间常来不及刷盘,尤其没配imkmsg或 kdump 时基本为空
从 Call Trace 里快速定位肇事模块
调用栈不是从上往下读,而是从最底端(panic 或 __warn 所在行)往上推,盯住第一个非通用内核函数:
- 看到
[nvidia]、[zfs]、[wireguard]这类方括号包着的名字?90% 是它——第三方模块未适配当前内核,尤其升级后没重装 ko 文件 - 反复出现
ext4_writepages、ext4_da_write_begin?文件系统层异常,立刻跑smartctl -a /dev/sda查磁盘 SMART,并确认挂载参数没用data=journal - 全是
mm_*开头(如mm_page_alloc、try_to_unmap)?内存子系统出问题,配合dmesg -T | grep -i "ecc|correctable"查硬件级内存错误 - 报
unknown symbol或invalid opcode?内核模块符号表不匹配,或 CPU 微码过旧(cpupower frequency-info+ 查 BIOS 更新日志)
验证 vmcore 是否真的能用
/var/crash/ 下有 vmcore 不代表它有效——常见失效比你想象中更琐碎:
- 先用
file /var/crash/*/vmcore确认类型:必须是ELF 64-bit LSB core file x86-64;若显示data或empty,说明crashkernel内存预留不足,或写入过程被截断 - 运行
crash /usr/lib/debug/lib/modules/$(uname -r)/vmlinux /var/crash/*/vmcore后输bt,若卡住或报cannot determine vmcore type,大概率是 debuginfo 包版本不匹配,或 vmlinux 路径不对 - debuginfo 必须严格对应当前崩溃内核版本:
find /usr/lib/debug/lib/modules/ -name "vmlinux" | grep $(uname -r),缺就补装(Ubuntu 装linux-image-$(uname -r)-dbgsym,RHEL/CentOS 装kernel-debuginfo-$(uname -r))
真正的难点并非在于命令的输入,而是要能够准确区分“日志中所记录的内容”与“其实际所代表的含义”。举个例子,同样是这句 Kernel panic - not syncing: VFS: Unable to mount root fs,它可能是由于GRUB配置错误、initramfs缺少驱动、磁盘控制器出现故障,甚至可能是BIOS中的SATA模式被设置成了RAID但却没有安装对应的驱动所导致的——这就需要结合 dmesg 前几秒的PCI设备枚举日志来进行交叉判断。