ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

OpenEuler服务器宕机定位:从现场证据到内核分析

OpenEuler服务器宕机定位:从现场证据到内核分析 处理过几十台宕机服务器之后我最深刻的感受是OpenEuler服务器宕机定位流程真正的瓶颈不在分析工具而在宕机后你有没有把正确的信息留下来。电源灯亮着、风扇转着、远程死活连不上进了机房按键盘也没反应——这种场景下如果直接重启你就把最有价值的第一现场抹掉了。这篇内容围绕“错误位置排查”展开覆盖宕机性质判断、现场证据抢救、vmcore分析、内存/文件系统/硬件分路排查最后用一个我实际处理过的NVMe IO挂死案例把整条链路串起来。适合刚接触服务器运维的工程师也适合有经验但想系统梳理一遍宕机排查思路的人。1. 先分清“死透了”还是“假死”宕机性质决定排查方向1.1 “死透了”和“假死”在运维上的本质区别宕机不是单一故障而是多种故障的共同结果。同一个“远程连不上”可能是内核panic彻底停摆也可能是某个进程把CPU占满导致系统假死还可能是IO卡死让所有任务都在等待。它们对应的证据来源完全不同panic靠vmcore和dmesglockup靠NMI和watchdog日志IO hang靠块设备和文件系统日志OOM靠内存监控。所以第一步不是打开日志乱翻而是先回答一个问题这台机器现在属于哪一类。有一次我接到报障说“机器ping不通”到现场发现iBMC能通、串口还在出字符那就不是内核panic而是用户态假死。最后追下去是数据库触发OOM后系统疯狂换页swap写满导致SSH和网络服务全部卡住。如果当时按老思路直接硬重启那一堆“Out of memory”日志就全丢了根因永远查不出来。分清性质和假死排查方向会完全不同。1.2 五条现场测试快速判断宕机性质机器还在现场、还没重启之前按顺序做下面几件事每一条都能帮你排除一批可能性。第一看键盘灯和面板状态。按Caps Lock或Num Lock如果键盘灯有反应说明CPU和中断基本还活着至少不是彻底的hard lockup如果完全没反应大概率CPU已经卡死或者内核把中断关掉了。服务器如果没有标准键盘接口这一步可以跳过但机房里有KVM时非常快。第二检查BMC/iBMC和串口SOL。管理口能ping通、SOL能登录说明硬件平台还活着如果SOL上还能看到内核输出说明系统还没完全死。反之管理口都进不去或者连BMC也失联问题可能已经下探到主板/电源/CPU层面。第三尝试Magic SysRq。前提是系统里 /proc/sys/kernel/sysrq 非零这一步要在平时就打开。真到宕机时用键盘AltSysRq功能键或者通过串口发送BREAK序列如果系统只是假死串口上会出现内核任务列表或内存信息如果发出去毫无反应那内核调度器大概率已经不工作了。很多老运维靠这一招就能区分“能救”和“必须硬重启”。第四看网卡灯和BMC事件日志。网卡指示灯异常熄灭或者iBMC里刚报过“system hung”“PCIe error”“CPU internal error”这些事件本身就是硬件侧的错误位置线索。别小看BMC那几条记录很多内存和CPU故障在messages里只字未提却在BMC SEL里写得明明白白。第五有带外条件就触发一次NMI。x86服务器可以从BMC/iBMC发送NMI中断给内核如果内核还响应中断NMI会触发panic并落进kdump如果触发后既没panic也没重启CPU多半已经死锁问题在硬件层。这一条非常实用但要注意触发NMI相当于主动制造一次panic必须确认当前不在业务高峰期。提示SysRq和NMI在已经宕机的机器上基本不会造成额外破坏但平时没事不要随便往 /proc/sysrq-trigger 里写 c 或 s那是在主动制造崩溃。1.3 判断结果怎么影响后续步骤判断完性质再决定翻哪个日志效率会高很多。我把常见情况整理成一张表方便现场对照现象特征判断倾向首要排查方向控制台有panic堆栈SysRq无响应内核panicvmcore、dmesg、内核模块dmesg报soft lockup部分CPU还能响应软锁watchdog配置、驱动、RT调度NMI无响应键盘灯失灵硬锁/硬件死锁BMC事件、CPU/主板、固件日志有hung_task、IO errorBMC仍通IO hang块设备、文件系统、存储链路SSH卡死但内核有响应messages有oom-kill用户态OOM/假死内存、cgroup、swap这张表不绝对但能帮你决定先翻哪个目录而不是把messages从头到尾看三遍。所谓“错误位置排查”第一步就是圈定错误所在的大位置是内核、是驱动、是文件系统、还是纯用户态。位置圈得越准后面每一步都越省时间。2. 重启之前必须抢救的现场证据日志、串口与内核转储2.1 日志持久化定位的第一道防线OpenEuler的日志体系是systemd-journald加rsyslog。journald如果不做持久化重启之后只有当前启动的日志宕机前那次启动的记录会直接消失。很多人在现场敲journalctl -b -1想看上一次启动的日志结果提示“No journal files found”那一刻的心情我太理解了。所以新装机的OpenEuler我第一件事就是改/etc/systemd/journald.conf把Storagepersistent打开确认/var/log/journal目录可写。这个操作不解决宕机但它决定了宕机之后你手里还有几张底牌。磁盘空间够的话还可以顺手设一下SystemMaxUse4G避免日志无限增长。这一步做得越早等真正出事的时候越从容。2.2 “第一现场”证据清单宕机后的黄金抢救期其实是系统还在通电、还没重启的这段时间。按优先级收集以下信息控制台或串口的最后输出如果屏幕还能显示拍照或录屏最后二三十行往往就是崩溃前的状态。串口若接在BMC SOL上部分BMC会保留一段回显记得回去翻缓存。/var/log/messagesOpenEuler上最核心的文本日志内核消息、服务启停、调度记录都会进来。优先看宕机时间点前后30分钟重点搜 panic、oom、hung_task、Call Trace。journald持久化日志journalctl --since 03:00 --until 03:10 -p warning先看warning以上级别过滤掉大量无意义info。/var/crash 和 /var/lib/systemd/coredump前者是kdump落盘目录后者是用户态coredump有文件就意味着有完整的“案发现场”。/proc/cmdline 和 /var/log/dmesg确认启动参数里有没有crashkernel、console串口参数以及硬件探测阶段有没有异常。BMC SEL和IPMI事件很多服务器宕机后会留下硬件事件比如“CPU thermal trip”“PCIe error”“DIMM CE/UE”这些是硬件错误位置最直接的证据。信息源关键路径能回答什么问题内核日志/var/log/messages、journalctl宕机时内核在做什么崩溃转储/var/crash/*/vmcore内核panic的完整栈用户态崩溃/var/lib/systemd/coredump哪个应用崩了、崩在哪硬件事件BMC SEL、/var/log/mcelog内存/CPU/PCIe硬件错误启动参数/proc/cmdlinekdump和串口有没有配置2.3 kdump有没有配置决定你能挖多深kdump是Linux内核崩溃转储机制。内核panic时系统会保留一块crashkernel内存给捕获内核把崩溃瞬间的内存映像写到磁盘。没有vmcore很多内核栈只能靠事后猜有了vmcore你可以直接用crash工具打开看崩溃函数、调用栈、各CPU状态几乎等于拿到了事故现场的高清录像。检查是否配置两条命令就够了grep -o crashkernel /proc/cmdline systemctl status kdump如果/proc/cmdline里没有crashkernel或者kdump服务是inactive那就要尽快补上。安装配置步骤也不复杂安装组件dnf install kexec-tools crash同时确保debuginfo源里有对应内核的kernel-debuginfo包。编辑/etc/default/grub在GRUB_CMDLINE_LINUX里加crashkernel512M。重新生成grub配置grub2-mkconfig -o /boot/grub2/grub.cfg。UEFI机器路径可能是/boot/efi/EFI/openEuler/grub.cfg注意区分。启动服务systemctl enable --now kdump。重启一次让crashkernel生效然后回来看cat /proc/cmdline。我见过很多机器配了kdump但从没真正触发过所以我建议每隔半年做一次panic演练在维护窗口里执行echo c /proc/sysrq-trigger确认/var/crash能正常生成vmcore再恢复业务。没有这一步真出问题时kdump可能因为路径权限、磁盘空间或镜像不对压根落不了盘。3. 内核崩溃的核心定位从vmcore到崩溃函数与调用栈3.1 用crash打开vmcore的完整流程拿到vmcore之后先确认两件事故障机的内核版本和vmcore文件完整性。uname -r和ls -lh /var/crash/时间-主机名/vmcore版本对不上后面所有分析都是白做。然后搭建分析环境。如果你有一台同架构的Linux机器直接在那边装工具dnf install crash dnf install kernel-debuginfo-$(uname -r)如果找不到debuginfo包先确认debuginfo源已启用。拿到vmlinux和vmcore后进入crashcrash /usr/lib/debug/lib/modules/$(uname -r)/vmlinux /var/crash/2025-01-01-03:10/hostname/vmcore如果默认路径找不到vmlinux用find /usr/lib/debug -name vmlinux定位。进入crash之后最常用的命令就几个bt打印panic时的调用栈这是定位崩溃函数的核心命令。log显示崩溃前的内核日志相当于把dmesg缓冲整个拉出来。ps看当时的进程列表谁在跑谁被卡住。sym把内存地址转换成函数符号。dis反汇编指定地址看具体指令。作为定位流程优先bt和log这两个能回答“错误位置在哪个函数、哪个子系统”。3.2 理解panic输出里的“错误位置”典型的内核panic日志会有一行类似这样的内容RIP: 0010:ext4_do_update_inode0x1e5/0x2a0 Call Trace: __jbd2_journal_commit_transaction0x8f/0x1b0 ? kmem_cache_alloc0x12/0x90 ...RIP是CPU实际执行到崩溃点时的指令地址ext4_do_update_inode0x1e5/0x2a0意思是崩溃在ext4_do_update_inode这个函数内部整个函数大小0x2a0崩溃点距离函数开头偏移0x1e5。Call Trace从下往上读越往下越是调用者越往上越接近崩溃现场。真正需要关注的是栈上没带“?”号的稳定调用链带“?”的行只是栈上残留地址不一定真的执行过。不同panic消息对应的错误位置也不太一样常见的几种Kernel panic - not syncing: Fatal exception某个oops升级成了panic通常是空指针或非法内存访问。Kernel panic - not syncing: Out of memory and no killable processes内核自己也分配不到内存比用户态OOM严重得多。Kernel panic - not syncing: Attempted to kill init!init进程被杀死systemd都撑不住了。BUG: unable to handle kernel NULL pointer dereference at ...最常见的空指针崩溃后面跟的地址往往是0x0附近。这些文字本身就在告诉你错误的大位置配合RIP和调用栈可以精确到函数级别。3.3 没有vmcore怎么反推没有配置kdump的情况下就只能靠日志拼图journalctl -b -1 -k看上一次启动的内核日志重点找最后200条。翻/var/log/messages里宕机时间点附近先搜panic、oops、BUG、Call Trace、Out of memory、hung_task。确认系统是否重启过uptime和last reboot -x能反推宕机时刻。检查有没有SysRq触发的痕迹这类日志会写进dmesg缓冲。如果只是用户态无响应但内核还活着看登录日志、cron日志、服务状态有时能发现是某个脚本或进程把内存/磁盘耗尽。没有vmcore的反推有点像拼图只给你最后几块。这也是我一再强调提前配置kdump的原因——它可能是你唯一能看到完整内核调用链的机会。4. 按“错误位置”分路排查内存、文件系统、硬件与驱动4.1 内存错误OOM与硬件位翻转是两个世界OpenEuler上内存耗尽不一定会panic更多时候是OOM killer把某个进程杀掉。日志关键行长这样Out of memory: Kill process 12345 (postgres) score 72 or sacrifice child Killed process 12345 (postgres), total-vm:10240000kB这说明错误位置在应用层是某个用户态进程把内存吃满了而不是内核坏了。继续用dmesg | grep -i out of memory和journalctl -p err找再配合cgroup的memory.events看是不是超了限额。硬件内存错误则是另一回事。MCEMachine Check Exception是CPU发现硬件错误后的上报机制日志会类似mce: [Hardware Error]: Machine check: Memory Error ... bank1这种错误的物理位置是内存条或CPU cache必须用memtest86/memtester或者BIOS内存测试验证同时看BMC SEL里的DIMM记录。技巧内存很大的机器日常记录一下edac模块的/sys/devices/system/edac/mc/mc0/ce_count如果这个值在持续增长说明有根内存条正在老化应该趁着业务低峰期换掉别等宕机后再查。4.2 文件系统错误XFS/ext4的“位置”链条文件系统引发的宕机日志关键词往往不是panic而是EXT4-fs error (device sdb1): ext4_lookup: ...: inode #12345: ... XFS (dm-0): metadata I/O error in xfs_trans_read_buf at daddr 0x...分析顺序应该是从下往上块设备层错误、文件系统层错误、应用层无响应。错误位置越往下越偏向硬件越往上越偏向文件系统逻辑。命令行排查按这个顺序来smartctl -H -d sat /dev/sda # 检查硬盘健康 smartctl -l error /dev/sda # 查看历史错误位置LBA multipath -ll # 如果用了multipath看路径健康状态如果磁盘SMART干净但文件系统报错要查阵列卡日志比如storcli的storcli /c0 show events。还有一个容易被忽略的点块设备超时时间。如果存储响应很慢内核默认的IO超时可能导致请求永久挂起最终触发hung_task宕机。针对慢速存储可以调/sys/block/sdX/device/timeout让错误更快反馈到上层。4.3 硬件/驱动MCE、PCIe AER与第三方驱动PCIe设备报错也经常导致宕机尤其是严重级别为Fatal时。日志类似PCIe Bus Error: severityUncorrected (Fatal), reported by 0000:03:00.0错误位置就在那个PCIe设备上用lspci -vvs 03:00.0看设备详情再结合是否新换过硬件或固件。这类问题经常出现在网卡、RAID卡、GPU上。第三方驱动是另一个高频“错误位置”。最典型的场景是新装网卡驱动或GPU驱动之后没几天就宕机。判断方法崩溃栈里是否有驱动函数名比如ixgbe_xmit_frame、i40e_clean_rx_irq、nvidia_drm_*。用lsmod和modinfo对比“最近变更窗口”内的模块。检查驱动版本和内核版本的兼容性。OpenEuler对内核模块管理比较严格建议用dkms或官方RPM包安装不要手动insmod一个来源不明的ko出了问题连跟踪都难。4.4 用户态与systemd视角的错误位置宕机不全是内核问题。有时候是一个关键服务卡死导致系统“假死”。看systemctl status有没有failed单元systemd-analyze blame看启动时有哪些服务耗时异常coredumpctl info可以查用户态应用崩溃时的调用栈。如果崩溃在用户态定位方式完全不同用gdb加调试符号看core文件而不是crash工具。还有一点如果系统配置了自动重启比如内核参数panic10或systemd单元Restartalways你看到的现象可能是“频繁重启”而不是“一次宕机”。这时候要抓重启周期的规律比如每天凌晨四点都来一次那大概率是定时任务或监控脚本触发的而不是硬件故障。5. 完整案例复盘一次OpenEuler 22.03服务器半夜宕机的定位全程5.1 现场现象与环境某数据中心一台跑PostgreSQL的OpenEuler 22.03 LTS SP3服务器内核版本5.10.0-136.12.0.0.11.oe2203sp3.x86_64磁盘是两块NVMe SSD做的软RAID1。凌晨三点多业务监控发现连接全部中断BMC显示OS no response。值班同事没多想就强制重启起来后业务恢复但大家心里都没底怕第二天再来一次。5.2 排查链路还原开机后我先做三件事。第一看uptime和last reboot -x确认宕机时刻在03:11左右。第二用journald查上次启动的日志journalctl --since 03:00 --until 03:15 --prioritywarning结果很典型03:10:48 kernel: INFO: task kworker/u4:2 blocked for more than 120 seconds. 03:10:48 kernel: echo 0 /proc/sys/kernel/hung_task_timeout_secs disables this message.这说明系统已经进入hung_task状态。第三往前翻到03:08附近看到一连串03:08:11 kernel: blk_update_request: I/O error, dev nvme0n1, sector 80251140 op 0x1:(WRITE) 03:08:12 kernel: nvme0n1: I/O error到这里基本可以确定宕机不是内核代码bug而是NVMe块设备IO错误把请求卡住最终触发hung_task系统失去响应。这台机器当时没有配置kdump所以没有vmcore可分析但也正因为根因在块设备层日志链已经足够清楚。接着用smartctl确认硬件状态smartctl -H /dev/nvme0n1 smartctl -a /dev/nvme0n1 | grep -E Media_Errors|Critical_WarningSMART整体状态是FAILEDMedia_Errors不为零。再查BMC SEL同时间段有一条“PCIe Correctable Error”记录位置指向PCIe总线。问题链路就完整了NVMe盘介质错误导致写入IO长期阻塞block层无法完成IOhung_task触发系统无响应。5.3 复盘教训这个案例里最容易忽略的三件事第一别只看最后一条hung_task。很多人一看到hung_task就以为是内核bug其实它只是一个结果。真正的错误出现在更早的“I/O error”必须把时间往前推找到第一个报错那才是错误位置。第二硬件问题不一定表现为MCE。NVMe设备出问题日志里更多是blk_update_request和nvme驱动的报错而不是MCE。所以排查硬件不能只搜“Machine Check”。第三OpenEuler上建议提前设置内核panic行为和kdump。比如在/etc/sysctl.conf里加kernel.hung_task_timeout_secs300 kernel.panic10再配上kdump这样即使出现严重IO挂死系统也能在可控时间内触发panic落盘拿到vmcore之后再深入分析而不是只能靠smartctl事后猜。第四日常就要监控NVMe的critical_warning和media_errors。很多环境完全没有这种监控反而要等宕机后才查。有了这些指标盘坏之前就能预警。5.4 这个案例还能怎么扩展如果系统里跑的是关键应用可以进一步优化IO路径。比如给内核加nvme_core.io_timeout60让单盘IO错误更快反馈到上层而不是无限阻塞同时用multipath或硬件RAID提供冗余。如果确认是盘本身坏直接热插拔更换如果是固件bug更新NVMe固件后再观察。这个案例的内核定位其实相对简单因为根因在块设备层。真正难的是那些“kernel panic vmcore”的场景那种情况要在crash流程里花更多时间。如果把“错误位置”当成坐标去查先从硬件、再查驱动、最后进入内核绝大多数宕机都能在半小时内找到方向。排查宕机这件事做得越久越觉得真正专业的做法不是宕机后反应快而是宕机前已经把路铺好。kdump、日志持久化、串口console、BMC事件上报这几样加在一起才是一套完整的OpenEuler服务器宕机定位流程。你提前十分钟做这些配置可能省下宕机后的十个小时。下次再遇到服务器“死透了”你会感谢当初那个愿意在维护窗口里多敲几条命令的自己。
返回列表