应优先使用dmesg -t | grep -a 20 -b 5 -e "(kernel panic|oops|bug:|call trace:)"提取带时间戳的 panic/oops 上下文,因默认 dmesg 混杂大量噪音;系统重启后需查 /var/log/kern.log.1.gz,而 journalctl 常漏捕 panic 瞬间;vmcore 必须用 crash 工具配合匹配的 vmlinux 解析,不可直接 cat。

直接看 dmesg 里带 panic/Oops 的段落
内核错误日志不是散落在各处的普通文本,真正要命的线索集中在 Kernel panic、Oops、BUG: 或 Call Trace: 这几类标记附近。默认 dmesg 输出太长,混着启动日志和驱动噪音,容易漏掉源头。
用这句命令快速定位有效上下文:
dmesg -T | grep -A 20 -B 5 -E "(Kernel panic|Oops|BUG:|Call Trace:)"
-
-T加人类可读时间戳,避免靠 uptime 换算出错 -
-B 5往上取 5 行——很多 panic 是由前面的WARNING:或内存分配失败引发的 -
-A 20往下取 20 行——确保拿到完整的调用栈,尤其是末尾的函数名 - 如果系统已重启,
dmesg缓冲区可能被覆盖,优先查/var/log/kern.log.1.gz:zcat /var/log/kern.log.1.gz | grep -A 20 -B 5 "Kernel panic"
别只信 journalctl -k
journalctl -k 看起来方便,但它和 dmesg 一样,都读的是内核 ring buffer。一旦缓冲区满或系统重启,早期 panic 日志就没了。更关键的是:journal 日志依赖 rsyslog 或 journald 持久化配置,而 panic 发生时,用户态日志服务很可能已经失效。
所以:
- 实时排查时,
dmesg -w比journalctl -f -k更可靠——它绕过用户态日志管道 - 查历史 panic,优先翻
/var/log/kern.log(Debian/Ubuntu)或/var/log/messages(RHEL/CentOS),前提是 rsyslog 启用了imkmsg模块 -
journalctl -b -1 | grep panic基本不可靠——上一次启动的 journal 可能根本没捕获到 panic 瞬间
vmcore 不是日志,不能 cat 查看
vmcore 是二进制内存镜像,不是文本日志。用 cat、less 或 strings 打开只会看到乱码或空内容,还可能卡住终端。
它必须配合对应内核版本的 vmlinux 调试符号文件,用 crash 工具解析:
crash /usr/lib/debug/lib/modules/$(uname -r)/vmlinux /var/crash/*/vmcore
- 先确认
vmlinux存在:find /usr/lib/debug/lib/modules/$(uname -r) -name vmlinux 2>/dev/null - 进入
crash后第一件事是输bt——看当前 CPU 的调用栈,这才是 panic 的直接现场 - 如果
crash报cannot determine或栈全是问号,说明vmlinux版本不匹配,或者vmcore本身无效(比如file vmcore输出不是 ELF core file)
哪些日志路径值得立刻检查
不同发行版和配置下,内核错误会落到不同位置,别只盯着一个地方:
-
/var/log/kern.log:Debian/Ubuntu 默认由 rsyslog 持久化内核消息,含 panic 前后完整上下文 -
/var/log/messages:RHEL/CentOS 传统路径,但需确认 rsyslog 配置了kern.*规则 -
/var/log/dmesg:开机时dmesg输出的快照,只保留启动阶段信息,对运行中 panic 无用 -
/var/crash/*/dmesg.*:kdump 生成的崩溃时刻内核日志文本副本,比 ring buffer 更完整,且不会被后续日志覆盖 -
/proc/sys/kernel/panic:这个值如果是0,panic 后系统直接停机,kdump 根本没机会触发——得设成非零(如10)
最常被忽略的是:所有这些路径里的文件,多数需要 sudo 权限才能完整读取,尤其 auth.log 和 kern.log。权限不足时,journalctl 有时反而更友好,因为它走的是 systemd 的访问策略。











