从一次服务器宕机排查说起:我是如何用dmesg命令揪出‘真凶’的
从一次服务器宕机排查说起:我是如何用dmesg命令揪出‘真凶’的
凌晨3点17分,监控系统突然弹出一条告警——生产环境的某台Web服务器响应超时。当我通过SSH连入机器时,发现所有HTTP请求都被挂起,连最简单的ls命令都需要近10秒才能返回结果。更诡异的是,top显示CPU和内存占用率都处于正常范围,系统负载平均值却飙升至15(而该服务器仅有8核)。这种矛盾的数据表现,让我意识到问题可能出在内核层面。
1. 现象分析与初步排查
面对这种"系统整体卡顿但资源指标正常"的诡异现象,我首先排除了几个常见诱因:
- 网络问题:
ping测试显示内网延迟<1ms,排除 - 磁盘I/O瓶颈:
iostat -x 1显示各设备util均低于30% - 内存泄漏:
free -h确认可用内存充足,无OOM迹象
此时,系统日志/var/log/messages中一条关于journald的报错引起了我的注意:
systemd-journald[XXXX]: Failed to write entry (22 items, XXXXX bytes), ignoring: Read-only file system这暗示文件系统可能进入了只读模式。但mount命令显示所有挂载点仍为rw状态,矛盾再次出现。
提示:当系统表现与监控数据出现矛盾时,往往意味着底层发生了非常规故障,此时需要直接检查内核级日志。
2. dmesg的深度应用实战
2.1 时间戳解读技巧
直接运行dmesg会输出大量信息,我习惯先使用-T参数转换为人类可读时间:
dmesg -T | tail -20关键输出片段:
[Sun Aug 20 03:15:42 2023] XFS (sdb1): Metadata I/O error in "xfs_imap_to_bp+0x45/0x60 [xfs]" at daddr 0x841e40 len 32 error 5 [Sun Aug 20 03:15:42 2023] XFS (sdb1): xfs_do_force_shutdown(0x2) called from line 1462 of file fs/xfs/xfs_trans.c. Return address = 0xffffffffa038a06d这些日志揭示了真相:XFS文件系统在sdb1分区遇到了元数据I/O错误,触发了强制关机流程。但为什么mount命令没有显示异常?因为此时内核尚未完成卸载流程。
2.2 日志级别过滤
通过-l参数聚焦错误级别信息:
dmesg -T -l err,crit输出浓缩为:
[Sun Aug 20 03:15:42 2023] blk_update_request: I/O error, dev sdb, sector 6789120 op 0x1:(WRITE) flags 0x800 phys_seg 1 prio class 0 [Sun Aug 20 03:15:42 2023] XFS (sdb1): Metadata I/O error [Sun Aug 20 03:15:42 2023] XFS (sdb1): xfs_do_force_shutdown(0x2) called2.3 设备健康诊断
结合smartctl工具验证磁盘状态:
smartctl -H /dev/sdb输出确认磁盘已失效:
SMART overall-health self-assessment test result: FAILED3. 故障机理深度解析
这次事故的本质是磁盘硬件故障引发的连锁反应:
故障阶段:
- 磁盘物理损坏导致I/O错误
- XFS文件系统检测到元数据损坏
- 内核触发保护性关机流程
矛盾现象解释:
表象 真实原因 mount显示rw 内核尚未完成卸载流程 系统卡顿 进程阻塞在I/O系统调用 负载飙升 大量进程进入D (uninterruptible sleep)状态 关键时间线:
dmesg -T | grep -E 'sdb|XFS' | head -5输出显示故障发展过程:
[Sun Aug 20 03:12:18 2023] sd 2:0:1:0: [sdb] tag#0 FAILED Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE [Sun Aug 20 03:12:18 2023] sd 2:0:1:0: [sdb] tag#0 Sense Key : Medium Error [current]
4. 解决方案与长效预防
4.1 紧急恢复步骤
- 隔离故障磁盘:
echo 1 > /sys/block/sdb/device/delete - 临时挂载为只读:
mount -o remount,ro /data
4.2 配置优化建议
在/etc/sysctl.conf中添加:
# 保留更多内核日志 kernel.printk_ratelimit = 5 kernel.printk_ratelimit_burst = 20 # 允许非root用户读取dmesg kernel.dmesg_restrict = 04.3 监控增强方案
创建定期检查脚本/usr/local/bin/check_disk_errors.sh:
#!/bin/bash ERROR_COUNT=$(dmesg -l err,crit | grep -c 'I/O error') if [ $ERROR_COUNT -gt 0 ]; then echo "$(date) - Found $ERROR_COUNT disk errors" >> /var/log/disk_health.log dmesg -l err,crit | mail -s "Disk Errors Alert" admin@example.com fi设置cron任务每小时执行:
0 * * * * /usr/local/bin/check_disk_errors.sh5. 高阶排查技巧
5.1 日志颜色标记
使用-L参数为不同级别日志着色:
dmesg -T -L=color颜色对应关系:
- 红色:emerg/alert/crit
- 黄色:err/warn
- 绿色:notice/info
5.2 实时监控模式
类似tail -f的功能:
dmesg --follow5.3 设施过滤技巧
只查看存储相关日志:
dmesg -f kern,disk这次事故让我深刻体会到,在Linux系统排障中,dmesg就像外科医生的内窥镜,能直接观察到系统最底层的运行状态。特别是在处理那些"表面指标正常但系统行为异常"的玄学问题时,直接检查内核日志往往是破局关键。现在我的运维手册里新增了一条:任何异常排查,dmesg -T -l err必须是第二步标准动作(第一步是看监控图表)。
