☰
Linux死机排查与自救:SysRq、kdump与日志分析实战
2026/10/8 23:56:12 网站建设 项目流程

简介:在Linux运维中,系统死机或内核崩溃往往难以从常规日志定位根因。这份资料系统梳理了三种获取崩溃现场信息的方法:Core dump面向应用程序异常,可捕获进程崩溃时的内存状态;Diskdump用于单机内核转储,无需网络即可保留内存与CPU状态;Netdump则适合不支持Diskdump的旧版本系统,可将崩溃信息发送至远程服务器分析。资源为doc格式文档,共1个文件,压缩包大小仅47KB,内容精炼但覆盖完整,包含各方法的配置命令、参数含义及操作步骤,如ulimit设置、diskdump设备初始化、netdump服务端与客户端配置等,并附有网卡是否支持netdump的判定思路。已有528人学习,适合Linux系统管理员、运维工程师及内核调试入门者参考,作为快速排查死机问题的实用笔记。

1. 死机不是玄学:先把Linux“假死”和“真死”分清楚

很多人一看到Linux操作系统死机,第一反应就是长按电源键强制重启。但只要你这么干过几次,就会发现有时候数据丢了、文件系统报错,甚至开机直接进不了系统。实际上,Linux死机至少可以分成两类:一类是“假死”,也就是内核还活着,只是桌面环境、SSH会话或者某个进程把资源吃死了;另一类是“真死”,内核完全停止响应,连SysRq键、网络、串口都没有任何反应。这两类情况的处理路径完全不同,前者可以用远程命令、魔术键甚至systemd工具救回来,后者只能靠提前配置的kdump和串口日志来找原因。这篇笔记就按“先判断、再自救、后修复、最后预防”的顺序,把一套能直接抄的Linux死机处理方法讲清楚,不管你是跑服务器的运维,还是玩嵌入式Linux的开发者,都能按步骤落到自己的环境里。

系统死机时最忌讳的就是慌乱。我们需要一个固定的排查顺序:先确认系统还有没有响应,再尝试低层自救,最后才是强制重启。下面所有方法都基于最常见的systemd、x86_64架构Linux发行版,嵌入式ARM设备我会单独提差异点。

2. 第一反应别乱按电源:用SysRq和SSH把系统从“假死”里拉回来

2.1 先判断系统还活着吗:ping、SSH、TTY三连测

发现死机先别着急碰电源。我的习惯是花三十秒做一次“三连测”:先ping对端IP,能通说明网络栈和内核调度还活着;再试一次SSH连接,能连上说明用户态进程还能跑;最后看看本机键盘的Caps Lock键,按一下看灯亮不亮——灯正常切换说明内核的中断处理还在工作。

如果ping不通但SSH能连,多半是网络服务假死;如果ping通但SSH连不上,可能是sshd进程被卡住或者连接数打满;如果ping、SSH都不行但Caps Lock灯有反应,说明内核还在,但用户态出问题了。这三连测的结果决定了下一步用哪套方案:本地TTY能切就切Ctrl+Alt+F1到F6,实在切不了就用SysRq。注意,很多系统默认没有开启TTY切换服务,或者显卡驱动崩溃导致显示层卡死,这时TTY也不一定切得过去,所以SysRq才是最后底线。

2.2 神奇键SysRq:内核级别的一套“后悔药”

SysRq是Linux内核内置的紧急调试机制,只要内核没完全崩溃,它就能执行一组预定义操作。常用的是Alt+SysRq+字母键组合,在笔记本上可能是Alt+Fn+PrtSc+字母。这组命令的顺序我习惯记成“REISUB”:R(unRaw,恢复键盘控制)、E(tErminate,给所有进程发SIGTERM)、I(kIll,发SIGKILL)、S(Sync,同步文件系统)、U(Unmount,只读重挂载所有分区)、B(reBoot,重启)。

这样一套下来,相当于让内核自己逐步结束进程、落盘数据、安全卸载文件系统再重启,比直接按电源键温和得多。注意R和E可能要等几秒,别连续狂按。前提是内核启用了CONFIG_MAGIC_SYSRQ且sysctl的kernel.sysrq值不是0。检查方法:

# 查看当前sysrq开关 cat /proc/sys/kernel/sysrq # 临时开启所有功能(重启失效) echo 1 > /proc/sys/kernel/sysrq # 永久开启,写入/etc/sysctl.d/99-sysrq.conf echo "kernel.sysrq = 1" > /etc/sysctl.d/99-sysrq.conf sysctl -p /etc/sysctl.d/99-sysrq.conf

参数说明:kernel.sysrq的值可以写成0到255的位掩码,1表示允许所有功能,4表示只允许同步文件系统,16表示允许重启。生产环境我一般建议设成1,因为关键时刻少一个功能就可能救不回来。嵌入式环境下,如果内核没有编译MAGIC_SYSRQ,这套键就完全无效,只能依赖串口或者看门狗。

2.3 还能进命令行时:用top、ps、dmesg找元凶

如果系统没完全死,还能进命令行,先别急着重启,趁现在抓现场。跑一个top看CPU和内存占用,重点找两个东西:一是CPU跑满的进程,二是内存占用量异常的进程。很多时候死机就是某个进程疯狂吃内存触发OOM,或者多个进程互相等待导致CPU空转。

# 按CPU占用排序,动态观察 top -b -n 1 | head -30 # 按内存占用排序 ps aux --sort=-%mem | head -20 # 查看最近内核日志,找panic、oom、hung_task dmesg -T | tail -50

逻辑说明:top -b -n 1表示批处理模式只输出一次,避免交互界面卡住;head -30只看头部。ps aux按内存降序,能快速锁定是哪个进程吃满了内存。dmesg -T里的关键字段是“Out of memory: Killed process”、“BUG: soft lockup”、“hung_task_timeout_secs”等,看到这些基本就能定位原因。如果dmesg输出刷屏,可以用dmesg -T | grep -iE 'oom|panic|hung|error'过滤。拿到这些信息后,如果能用kill命令结束元凶进程,死机可能在几秒内自愈;即使非要重启,这些日志也是后续排查的宝贝。

3. 死机前的常见诱因与系统日志:根据日志定位内核崩溃还是OOM

3.1 通过dmesg和journalctl看死机现场

不管是假死还是真死,重启前后都要尽量保留日志。systemd环境下的日志存在/var/log/journal/里,通常用journalctl来看。dmesg看的是内核环形缓冲区,重启后内容就没了,所以需要提前配置pstore或者串口记录。我的习惯是两步走:先看journalctl -k -b -1,这是上一次启动的内核日志(-b -1表示上一个boot),重点找最后几条记录;再用journalctl -n 200看本次启动的早期报错,因为很多死机原因会在下次启动时以“清理临时文件”、“recovering journal”的形式暴露。

# 查看上一个启动的内核日志,末尾就是死机瞬间 journalctl -k -b -1 -n 100 --no-pager # 查看本次启动的日志,找异常 journalctl -b -p err --no-pager

参数说明:-k表示只看内核日志,-b -1指定上一次启动,-n 100限制条数,--no-pager避免在死机后无法退出分页。第二条命令中-p err表示只显示错误级别及以上的日志,能快速定位本次启动是否出现了磁盘、文件系统、驱动相关的硬错误。如果journalctl提示“No journal files were found”,说明日志没持久化,需要在/etc/systemd/journald.conf里把Storage改为persistent。

死机如果发生在OOM(内存耗尽)时,日志里会出现“Out of memory: Killed process 1234”这样的行。如果死机时按SysRq键没反应,日志里可能出现“NMI watchdog: BUG: soft lockup”,说明某个CPU核心在内核态死循环,通常是驱动问题。还有“hung_task_timeout_secs”相关的“blocked for more than 120 seconds”,说明有进程在等待IO超时,常见于NFS挂载点失联或者磁盘故障。

3.2 OOM Killer、磁盘满、僵尸进程:三类高频原因怎么确认

第一类OOM。确认方法除了看dmesg,还可以看系统原来的内存水位线。当内存严重不足时,内核会调用OOM Killer杀掉最吃内存的进程。但如果杀完还是满,系统就可能陷入反复杀进程的循环,最终表现为卡死。解决方向是调整vm.overcommit_memory、给关键进程加OOMScoreAdjust,或者直接加物理内存/swap。

第二类磁盘满。很多人忽略/tmp、/var/log这类分区满了会死机。尤其是日志分区满了,syslog和journald会一直重试写日志,导致进程阻塞。确认方法:

# 查看各分区使用率 df -hT # 查看inode使用率 df -i # 找出超过1G的大文件 du -ahx / 2>/dev/null | sort -rh | head -20

逻辑说明:df -hT带文件系统类型,du -ahx里的-x表示不跨文件系统,避免扫到挂载的其他盘。如果发现/var/log/journal占了几个G,可以直接用journalctl --vacuum-size=200M清理。记住,磁盘满时千万不要直接rm掉正在被进程写的日志文件,正确做法是清空文件内容:> /var/log/syslog,否则进程还握着旧文件句柄,空间依然不释放。

第三类僵尸进程。僵尸进程本身不占CPU,但如果父进程是init或者systemd,并且大量累积会导致PID耗尽,新的进程创建失败,表现就是看起来像死机。确认方法:

# 统计僵尸进程数量 ps -eo stat,ppid,pid,cmd | awk '$1 ~ /Z/ {print $0}' | wc -l # 查看PID上限 cat /proc/sys/kernel/pid_max

如果僵尸进程很多,大概率是某个父进程没有调用wait()回收子进程。解决办法是找到父进程然后重启它,而不是kill僵尸进程本身(kill不掉)。在这个场景下,pstree -p能找到父进程的PID,然后systemctl restart对应服务。

3.3 如果是显卡/驱动导致的花屏死机:怎么切换VT和禁用驱动

Linux桌面环境死机很大比例是显卡驱动惹的祸,尤其是NVIDIA闭源驱动和AMD某些旧驱动。现象是画面冻结、鼠标能动但点不了、黑屏或者花屏。这时候记住第一招:Ctrl+Alt+F1到F6切换TTY,很多情况下能切换到命令行界面。如果切换不了,试试SysRq的R和K恢复键盘控制。

切到TTY后,不要急着重启,先看日志。journalctl -b | grep -i nvidia或者dmesg -T | grep -i drm,常见故障是“GPU has fallen off the bus”、“failed to initialize”、“drm_gpu_reset”之类。应急手段是把驱动改成modeset=0:

# 以Intel核显为例,内核启动参数加modprobe.blacklist=nouveau # 编辑/etc/default/grub,在GRUB_CMDLINE_LINUX中添加 # GRUB_CMDLINE_LINUX="... nouveau.modeset=0" # 更新grub后重启 update-grub

参数说明:nouveau.modeset=0表示让nouveau驱动不进行模式设置,改用通用framebuffer,能避开很多花屏死机。NVIDIA闭源驱动可以加nvidia-drm.modeset=1,但如果问题出在驱动本身,更稳妥的是进单用户模式卸载驱动包,用开源的vesafb撑住桌面。嵌入式平台如果用的是DRM/KMS驱动,死机时优先看串口输出里的“drm_atomic_helper”相关报错,很多时候是显示时序配置错误导致整个显示栈挂起。

4. 真死机(硬件级)怎么处理:从强制重启到系统修复

4.1 强制重启之后的第一件事:检查文件系统

如果SysRq、SSH、TTY全部无效,那就是真死机,只能强制重启。笔记本长按电源10秒,台式机直接按复位键,服务器可以短按电源键触发ACPI断电(如果没配置为关机)。强制重启后最怕的是文件系统损坏,所以第一件事不是启动到桌面,而是检查根分区。

大多数ext4系统重启时会自动进入journal恢复,但有时会卡在“Give root password for maintenance”提示,这是因为根分区没有干净卸载,fsck可能要在单用户模式下人工跑。如果是服务器,我建议直接在GRUB菜单里选择“Advanced options for Ubuntu”然后选“recovery mode”,进到菜单后再选“fsck”。也可以手动在initramfs里执行:

# 在GRUB菜单按e编辑启动项,在linux行末追加 # init=/bin/bash # 然后Ctrl+X启动,进入单用户bash mount -o remount,rw / # 手动检查根分区,先看设备名 blkid fsck.ext4 -f /dev/sda2

参数说明:init=/bin/bash是跳过了systemd直接进bash,这时候根分区默认是只读的,所以先remount成rw。fsck.ext4的-f是强制检查,即使文件系统看起来干净也会全盘扫一遍。-y参数可以自动回答yes,但不建议在不明情况下直接用,可能会把不该删的inode也删了。执行完fsck后,按Ctrl+D或者直接reboot恢复正常启动。

强杀之后出现“Kernel panic - not syncing: VFS: Unable to mount root fs”这种报错,往往是根分区设备名漂移或者initramfs损坏。解决办法是在GRUB里指定正确的根分区,比如root=/dev/sda2或root=UUID=xxx。如果连initramfs都坏了,用live CD启动chroot进去重新生成:mkinitramfs -o /boot/initrd.img-$(uname -r) $(uname -r)。

4.2 开机进单用户模式修复损坏的包和配置

强制重启后系统能起来但各种服务异常,别急着用,先进单用户模式做一轮体检。现在的发行版按e编辑GRUB启动项,在linux行尾追加“systemd.unit=rescue.target”就能进入维护模式。在这个模式下网络是关的,只有root shell,适合修复因死机导致的包管理器状态不一致。

# 在维护模式下,重装可能损坏的包管理器 apt --fix-broken install # 或者重新配置所有未完成的包 dpkg --configure -a # 检查全部依赖是否正常 apt check

逻辑说明:强制断电可能导致dpkg的数据库状态损坏,出现“Package xxx is in a very bad inconsistent state”错误。dpkg --configure -a是修复不完全安装包的通用解。如果连apt都用不了,那就直接看/var/lib/dpkg/status文件的前几行,有没有空行或乱码,有就备份后恢复。另外,systemd服务因为断电可能残留很多“failed”状态,用systemctl list-units --failed --no-pager查看,然后逐个systemctl reset-failed清理。

还有一种经常被忽视的情况:死机时某个配置文件正好写到一半,重启后服务起不来。比如/etc/fstab被写坏,导致开机卡在“A start job is running for /dev/disk/by-uuid/xxx”。这时候进rescue mode,把fstab里有问题的行注释掉,或者改成noauto,让系统跳过挂载。

4.3 为下一次死机做准备:kdump和crash工具

真死机的根因排查不能靠猜,必须在正常运行时部署好“黑匣子”。最常见的是kdump,它在内核崩溃时用一个小内核抓取崩溃转储,存到磁盘上供crash工具分析。配置步骤要点总结在表格里:

项目推荐值 / 做法
内核版本与当前运行内核完全一致
crashkernel内存预留x86_64下建议256M,如果用kdump抓大内存,可以设crashkernel=512M
转储目标写到独立分区,比如/var/crash,不要写到根分区
测试触发echo c > /proc/sysrq-trigger

安装完kdump-tools后,把/etc/default/kdump-tools里的USE_KDUMP=1,然后确保grub启动参数里有crashkernel=256M。手动触发一次真实崩溃测试,确认能在/var/crash下生成vmcore文件。注意,提供crashkernel参数后重启,用free -h看总内存会减少一点,这是正常现象。不要为了省内存把crashkernel设太小,否则崩溃时没有足够内存转储。

如果不想用kdump,嵌入式环境可以用pstore/ramoops。内核开启CONFIG_PSTORE后,死机时的内核日志会保存在内存保留区,重启后能从/sys/fs/pstore/里读出来。很多ARM开发板默认支持ramoops,但需要设备树里配置好内存区域,否则读不到任何内容。这个方案的好处是断电也不丢,坏处是只能保留日志,没有完整的内存转储。

5. Linux死机处理避坑指南:5个我踩过的坑

5.1 现象:按电源键没反应,长按又怕丢数据

有次一台生产服务器假死,SSH断连,ping也不通,我按了一下电源键没反应,又长按了10秒强制断电。重启后发现数据库损坏了,恢复花了一整天。后来才明白,电源键没反应不代表内核死了,而是ACPI事件处理被卡住。正确做法是先试SysRq的S和U,让内核同步文件系统并重新以只读方式挂载。如果SysRq没开,但Caps Lock灯还能亮,说明内核活着,可以尝试插上网线等几秒,看网络栈会不会自愈。长按电源键一定是最后的选项,而且长按之前如果能等到几秒,给内核一个落盘的时间窗口,损失会小很多。

5.2 现象:SysRq没生效,原来是内核参数没开

笔记本上按Alt+Fn+PrtSc+字母键没反应,查了sysctl发现kernel.sysrq=0。有些发行版默认是0,有的默认是16(只允许sync)。在台式机上可以用无线键盘的话,SysRq键经常被映射到别的键上,导致组合键无效。解决办法是把sysrq值永久设成1,并且在物理键盘上测试。测试方法很简单:执行echo 1 > /proc/sys/kernel/sysrq后,按Alt+SysRq+H,如果TTY上能看到SysRq键的帮助信息,就说明生效了。如果你用的是笔记本,要确认Fn键是否被BIOS锁住,有些笔记本需要按Alt+Fn+PrtSc,但Fn本身又会被系统当成单独的Shift,导致组合键错乱。

5.3 现象:重启后fsck卡住,根分区没挂载

死机后重启,系统停在“/dev/sda2 contains a file system with errors, check forced”然后卡了很久。原因是根分区没有干净卸载,e2fsck在启动时自动干预,但检查过程非常慢,尤其在几T的大分区上。这时不要慌,等它跑完即可。但如果卡在“Checking for bad blocks”这种只读测试上,说明磁盘可能真的有物理坏道,直接Ctrl+C跳过bad block测试,先让系统起来备份数据。另外一个坑是,如果你在fstab里写了错误的fsck pass参数(比如根分区写成了0),开机就不会自动检查,损坏会越积越深。正确做法是:根分区fsck pass=1,其他数据分区pass=2,swap分区pass=0。

5.4 现象:日志被覆盖,死机现场没了

死机后想看journalctl -k -b -1,结果提示只有当前启动的日志,上个启动的日志已经被循环覆盖了。这是因为journald默认容量限制可能只有几十M,死机前大量报错把日志缓冲区塞满了。解决方法是设置合理的持久化容量:在/etc/systemd/journald.conf里把SystemMaxUse改成500M或更大,同时把RuntimeMaxUse也调大,否则重启后内存日志还是会丢。另外,建议提前开启pstore,这样即使内核panic,最后几百行日志也能留在/var/crash或/sys/fs/pstore里,不至于完全两眼一抹黑。我发现很多桌面Linux用户没装rsyslog,journald又没持久化,死机后连一点痕迹都没有,这算是最常见的失误。

5.5 现象:嵌入式设备死机,串口没输出

嵌入式Linux开发板死机时,串口终端可能什么都打不出来,原因是内核串口驱动本身卡死,或者printk级别设置太低。先检查内核启动参数里有没有console=ttyS0,115200,以及/proc/sys/kernel/printk的值。举个例子,printk默认可能是“4 4 1 7”,如果崩溃发生在比4更低的级别,就不会输出到console。建议开发调试阶段改成“7 4 1 7”甚至“8 4 1 7”,让所有级别的日志都打印。注意这会让串口输出刷屏,性能下降,但排查死机时值得。另外,ARM板子很多没有MAGIC_SYSRQ,所以别指望SysRq,得靠硬件看门狗。如果看门狗没喂上,死机后板子会在几十秒内自动重启,但重启后上一条日志可能没来得及保存,这时候需要把内核日志写到MTD分区或使用pstore。

6. 最后一个技巧:给死机装上“黑匣子”——自动触发coredump和kdump

都说死机不难处理,难的是不知道为什么会死机。所以我把最后的篇幅留给“让系统自己留证据”这件事。除了前面说的kdump,还有一个很容易被忽略的组合:systemd的coredump机制加内核的oops日志。当用户态进程崩溃时,systemd-coredump会收集core文件,存放在/var/lib/systemd/coredump/里。但死机通常发生在内核态,所以核心还是kdump。下面是最小配置方案:

# 安装kdump工具(以Ubuntu/Debian为例) apt install kdump-tools crash # 修改/etc/default/kdump-tools # 确保USE_KDUMP=1 sed -i 's/USE_KDUMP=0/USE_KDUMP=1/' /etc/default/kdump-tools # 在/etc/default/grub的GRUB_CMDLINE_LINUX里追加crashkernel=256M # 然后更新grub update-grub reboot

重启后检查crashkernel是否生效:

# 查看系统保留的crash区域 cat /proc/iomem | grep -i crash

看到类似“Crash kernel”的行,代表预留成功。然后用一个故意崩溃的内核命令测试:

# 触发一次内核panic(会丢未保存数据,最好在测试机上做) echo c > /proc/sysrq-trigger

触发后系统会自动重启,重启后检查/var/crash目录下是否生成了vmcore文件。如果生成成功,就可以用crash工具分析:

# 进入crash调试界面 crash /usr/lib/debug/boot/vmlinux-$(uname -r) /var/crash/202401010000/vmcore

逻辑说明:echo c > /proc/sysrq-trigger会让内核主动触发panic,这是验证kdump配置是否正确的标准做法。crash工具需要vmlinux符号文件,很多发行版没装,需要apt install linux-image-$(uname -r)-dbgsym之类调试包。没有调试符号也能看堆栈,但函数名会全是地址,定位难度大增。另一个实用技巧是配合netconsole,把内核日志通过网络发送到另一台机器,这样即使磁盘完全损坏,日志也留了一份。netconsole配置比较简单,写到/etc/sysctl.conf或启动脚本里,指向对端IP和端口即可。

我个人的教训是,死机处理最重要的不是“事后能修”,而是“事发时能救”,然后是“事后有证据”。现在每装一台Linux机器,我都会先做四件事:开启sysrq、持久化journald、配置crashkernel、设置串口日志输出。有些步骤会占用少量内存和磁盘,但比起死机后盲修,这点代价实在不值一提。希望这些方法能帮你把处理Linux死机的时间从几小时压缩到几十分钟,也希望你永远用不上SysRq那套组合键——但真到了那一刻,你会庆幸自己提前看过这篇。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询