想象 一下,我们正在 Linux 系统上愉快地工作,编译软件包、运行更新,或者只是浏览网页,突然屏幕卡住了,屏幕上出现了一长串神秘的文字:”Kernel panic – not syncing: Attempted to kill init!”
在开始紧张之前,让我们静下心来,学习如何理解、模拟和处理内核崩溃(Kernel Panic)故障。
1] 什么是 Kernel Panic
简单来说,内核崩溃 (kernel panic) 是 Linux 内核在遇到无法安全恢复的严重错误时采取的一种安全措施。
Linux 内核是系统的核心,负责处理从内存管理、设备通信到进程运行的所有事务。当内核深处出现问题时(例如,错误的驱动程序访问了无效内存或关键组件发生故障),内核会暂停运行以避免进一步的损害。
可以把它想象成汽车的紧急刹车:当情况即将变得非常糟糕时,系统会猛踩刹车,停止一切运行。
2] Kernel Panic 的常见原因
让我们来看看 Kernel Panic 背后的常见原因,它们也是 Linux 系统崩溃的一些最常见原因:
- 内存故障、CPU 过热或磁盘故障是常见的硬件问题,这些问题会导致内存损坏、系统不稳定或严重的文件系统错误,从而引发内核崩溃,尤其是在启动过程中
- 手动安装的或是第三方的驱动程序与当前内核版本不匹配时可能会立即引发内核崩溃,尤其是在使用 modprobe 等工具加载时
- 关键文件(例如 /etc/fstab、/sbin/init)损坏或 initramfs 映像损坏可能会导致无法正常启动,并引发内核崩溃
- 错误的 UUID、分区标签或 GRUB 中缺少 kernel/initramfs 条目可能会导致启动过程混乱,甚至在操作系统加载之前就引发崩溃
- 意外删除 /sbin/init 等重要文件或强制终止 PID 1 将导致不可恢复的内核崩溃,因为系统会丢失其主进程
3] 如何安全地模拟内核崩溃
重要提示‼️:请勿在生产环境的系统上尝试此操作。请务必在虚拟机(VirtualBox、KVM 或 QEMU)或容器中进行测试。
选项 1:使用 /proc/sysrq-trigger 触发内核崩溃
模拟内核崩溃最安全、最可控的方法之一是使用 Linux 内核提供的 SysRq(系统请求)接口,开发人员和系统管理员经常使用该接口来调试崩溃场景或测试系统恢复策略(如自动重启)。
SysRq 接口通过 /proc/sys/kernel/sysrq 控制,要启用它,则运行如下命令:
$ echo 1 | sudo tee /proc/sys/kernel/sysrq
需要模拟内核崩溃时,则运行如下命令:
$ echo c | sudo tee /proc/sysrq-trigger
一旦执行此命令,内核就会停止,显示紧急消息,并冻结系统。
选项 2:使用崩溃内核模块(Crash Kernel Module)
一些内核包含专门用于触发崩溃的模块,可以使用如下命令加载它:
$ sudo modprobe crash
模块加载后,它可能会提供额外的调试功能,具体取决于该的内核配置。但是,并非所有发行版都包含此模块,出于安全考虑,它可能在生产内核中被禁用。
如果 modprobe crash 返回错误,则该模块可能不可用或未内置于当前使用的内核中。我们可以使用以下命令进行检查:
$ modinfo crash
4] 如何修复 Linux 中的内核崩溃
让我们逐步了解诊断和修复内核崩溃的过程。
1. 重启并查看系统日志
内核崩溃后,系统可能会完全冻结。我们需要手动重启机器,方法是按下电源按钮或使用 reset 开关。
系统重启(或从实时媒体启动)后,首先要检查系统日志,以确定崩溃的原因。可以使用 journalctl 命令,该命令将显示上次启动的详细日志,包括内核错误和失败的服务:
$ journalctl -xb
或者,检查内核消息缓冲区和日志文件:
$ dmesg | less OR $ cat /var/log/kern.log | less
查找提及 “panic”、”segfault”或者”kernel bug”的行,关注对应的模块名称、硬件错误或文件路径。
2. 使用旧的内核启动系统
内核更新后,系统经常会因为驱动程序不兼容或内核构建错误而崩溃。幸运的是,GRUB 通常会保留多个已安装的内核版本,让我们可以轻松回滚。
要启动到旧内核,只需重启系统,在 GRUB 菜单上按 Esc 键(如果菜单没有自动显示),选择菜单中的”Advanced options”条目,然后从列表中选择一个之前的内核版本——例如,如果较新的 6.x 内核导致问题,则选择 5.15.0-92-generic。
找到稳定的内核版本后,可以将其设置为默认版本,这样 GRUB 就会始终自动启动到该版本。
$ sudo apt install linux-image- $ sudo grub-set-default 1 # 设置默认使用旧内核启动
使用”grep menuentry /boot/grub/grub.cfg”来查找所需内核条目的确切名称。
3. 重建 Initramfs(初始 RAM 文件系统)
initramfs(或 initrd)是一个小型的临时根文件系统,在启动过程中,在实际的根文件系统挂载之前加载到内存中,其中包含启动系统所需的基本驱动程序和工具。
如果此映像损坏、与内核不兼容或完全丢失,则系统可能会在 GRUB 将控制权移交给内核后立即崩溃。
要重建 initramfs,如果系统已经无法启动,则可以启动 Live 模式并挂载根分区。然后执行如下命令:
$ sudo update-initramfs -u -k all
如果只想为当前内核重新生成:
$ sudo update-initramfs -c -k $(uname -r)
重建完成后,重新启动系统。
4. 修复文件系统
如果内核崩溃包含类似”无法挂载根文件系统 (unable to mount root fs)”或”VFS: 无法挂载根文件系统 (VFS: unable to mount root)”之类的消息,则很有可能是根文件系统或启动文件系统已损坏,这可能是由于非正常关机、电源故障或磁盘错误造成的。
要修复文件系统,则使用 lsblk 或 fdisk 查看 Linux 系统的分区情况:
$ lsblk
查看好分区情况后,就可以使用 fsck 命令进行文件系统修复了(例如修复/dev/sda1分区):
$ sudo fsck /dev/sda1
5. 诊断硬件问题
有时,内核崩溃根本不是软件的问题,而是底层硬件默默地出现了故障。众所周知,内存和磁盘错误很难被发现,除非它们造成了真正的损害。
可以使用 smartmontools 软件包中的 smartctl 命令检查驱动器的健康状况和错误状态:
$ sudo smartctl -a /dev/sda
留意诸如 Reallocated_Sector_Ct(坏扇区已移动)、Pending_Sector_Ct(等待重新分配的扇区)或 Current_Pending_Sector(表示不稳定的重要危险信号)之类的警告信号。
如果这些值中的任何一个正在上升,则强烈表明主机的驱动器正在发生故障——请立即备份数据并更换磁盘。
6. 修复 GRUB Bootloader
GRUB Bootloader 引导程序配置错误或损坏是导致内核崩溃的常见原因,尤其是在内核升级、双启动设置或磁盘更换之后。如果 GRUB 无法正确定位根分区或 initrd 映像,系统可能无法启动并抛出崩溃错误。
需要使用 Live CD 或可启动 USB 修复 GRUB问题:
$ sudo mount /dev/sda1 /mnt $ sudo grub-install --root-directory=/mnt /dev/sda $ sudo update-grub
确保 /etc/fstab 具有正确的 UUID,可以使用以下命令检查它们:
$ blkid
5] 如何避免内核崩溃
虽然内核崩溃无法完全避免,尤其是在硬件故障的情况下,但遵循一些明智的做法可以显著降低发生这种情况的几率。
以下是如何主动保护 Linux 系统免受内核崩溃的影响的几个方法:
- 避免手动删除或修改系统关键文件
- 切勿在未进行测试的情况下在实时生产服务器上更新内核
- 使用 LTS(长期支持)内核以确保稳定性
- 始终至少安装两个内核版本
- 使用备份(尤其是 /boot、/etc 和重要配置的备份)
- 使用 kdump 启用自动崩溃转储以捕获崩溃日志
6] 奖励内容:设置崩溃后自动重启
为了避免服务器因为崩溃卡死而影响业务,我们可以将内核配置为在崩溃后自动重启。
将此配置添加到 /etc/sysctl.conf 文件中,该配置文件指示系统在崩溃 10 秒后重启:
kernel.panic = 10
最后,使用如下命令使配置生效:
$ sudo sysctl -p
内核崩溃 (kernel panic) 可能看起来很可怕,尤其是对初学者来说。但一旦理解了它的含义以及如何处理它,它就不再是另一个需要解决的 Linux 难题了。
关键在于保持冷静,启动到恢复系统或实时系统,收集日志,识别哪些更改(内核更新、硬件故障、配置错误),并有条不紊地修复损坏。