Linux 内核日志分析与故障排查

2次阅读

dmesg关键日志需精准过滤而非全览:用dmesg -t | grep -i “Error|warn|fail|unable”筛选,结合硬件总线关键词、模块名对照lsmod、addr2line定位源码,oom需联动ps/cgroup验证,警惕“无报错=无问题”盲区。

Linux 内核日志分析与故障排查

怎么看 dmesg 里真正有用的那几行

内核日志不是日志,是线索拼图——dmesg 默认刷屏全是初始化信息,真出问题时关键报错往往被淹没在千行启动日志里。重点不是“看全”,而是“过滤准”。

实操建议:

  • dmesg -T | grep -i "error|warn|fail|unable" 加时间戳筛选(-T 需 root 或 sudo 权限)
  • 硬件类问题优先搜 pcinvmeatausb 等总线关键词,比如 dmesg | grep -A2 -B2 nvme
  • 驱动加载失败常表现为 modprobe: FATAL: Module xxx not found,但内核实际可能已静默 fallback 到通用驱动,得结合 lsmod/proc/modules 对照
  • 别信 dmesg -c 清空后“没报错=没问题”——有些错误只在设备热插拔或负载突增时触发,需配合 dmesg -w 实时盯梢

journalctl -kdmesg 输出不一致?

因为它们来源不同:dmesg 直读内核环形缓冲区(log_buf),而 journalctl -k 读的是 systemd-journald 持久化后的内核日志副本——缓冲区满会丢老日志,journald 可能因配置丢字段或截断。

实操建议:

  • 查最近一次重启前的错误,必须用 journalctl -k -b -1-b -1 表示上一次 boot)
  • 发现 journalctl -k 有内容但 dmesg 没有,大概率是内核缓冲区溢出,调大 kernel.printk_ratelimit 或改 kernel.log_buf_len(需 boot 参数)
  • journalctl -k 完全空白,检查 journald 是否禁用了内核日志捕获:grep -i "kmsg" /etc/systemd/journald.conf,确认 ForwardToKMsg=yes

dmesg 报错定位具体驱动或模块

内核错误行末尾常带 [xxxxx],那是模块名缩写,但不是源码模块名,而是内核符号表里注册的名称,和 lsmod 输出一致。

实操建议:

  • 看到类似 nvme 0000:01:00.0: PCIe Bus Error: severity=Correctable,其中 nvme 就是模块名,直接 lsmod | grep nvme 看是否加载、版本号
  • 报错含地址如 bug: unable to handle kernel NULL pointer dereference at 0000000000000000,用 addr2line -e /lib/modules/$(uname -r)/build/vmlinux 0000000000000000 反查(需安装 debuginfo 包)
  • 某些驱动(如 igbr8169)有多个变体,报错里模块名可能和 lspci -k 显示的 Kernel driver in use 不一致,此时以 lspci -vv -s xx:xx.x | grep -A10 "Kernel modules" 为准

为什么 dmesg 里有 OOM killer 记录却找不到进程被杀

OOM killer 日志(Killed process xxx (xxx) total-vm:xxxxkB, anon-rss:xxxxkB, file-rss:0kB)只记录它动手那一刻的状态,但进程可能已退出、被信号终止,或被容器 runtime 拦截并静默回收。

实操建议:

  • OOM 日志本身不含 PID 命令行,需立刻执行 ps aux --sort=-%mem | head -20 对照内存占用峰值
  • 容器环境(docker/podman)中,OOM 由 cgroup v1/v2 触发,dmesg 记录的是内核视角,实际 kill 由 runc 或 crun 执行,查 docker ps -apodman ps -a 看状态为 Exited (137)
  • 检查 /sys/fs/cgroup/memory/ 下对应 cgroup 的 memory.oom_controlmemory.events,确认是否启用 OOM killer

内核日志最危险的盲区不是看不懂报错,而是把“没报错”当结论——很多硬件降级、驱动静默 fallback、cgroup 节流都不会打 ERROR,只在 /procsysfs 留痕迹。

text=ZqhQzanResources