记一次 linux 系统无法启动修复过程
背景¶
我想要把第二张显卡也直通给虚拟机,然后就自己编译了一个打了 acs overide patch 的内核。之后启动也没有问题。但是当我第一次运行虚拟机后,电脑就卡死了。然后我强制关机后,无法进入系统,而进入了 busybox initramfs 交互命令行。提示文件系统错误,让我 fsck 系统盘。我照做后就成功进入系统了。
- 这里进入系统后一切正常,但是 lxc 的 storage 显示 unavailable,zpool import zfs_lxd.img 显示损坏。
然后我想再试试,结果启动虚拟机后又卡死了。我强制重启后,好像又进入 busybox 进行 fsck 了,但结果还是进不了系统,这次进入了紧急模式。
过程¶
紧急,emergency 模式¶
主要的报错是FAT-fs IO charset iso8895-1 not found
,
提示让我登录查看日志,我登录后 df -h,发现确实 efi 分区是没有挂载的。紧急模式下,其它命令好像都没啥问题,zsh 的配置都是我的 oh-my-zsh。
网上有一样的报错
- boot - 16.04 - stuck in emergency mode - FAT-fs (nvme0n1p1): IO charset iso8859-1 not found - Ask Ubuntu
- mount - Restore /boot/efi - Ask Ubuntu
但是他们提到的进入恢复模式,然后运行 depmod,我无法做到:
- 我不知道怎么进入恢复模式,因为我重启就会进入这个紧急模式无限循环
- 其实是因为我把 grub 设置为 hidden 并且延迟为 0,开启后就可以进入 grub 界面选择内核版本以及紧急模式
- 在紧急模式中我无法 fsck 系统盘,因为已经挂载了(efi 分区可以,但是没有错误)
- 紧急模式中无法运行 depmod 命令(这里其实已经反映问题了)
希望,livecd 修复¶
我以为是 efi 分区损坏了,在反复 fsck 无效后,我决定重建 efi 分区。于是通过 U 盘进入了 ubuntu20 的 livecd(22 版本启动很慢)
gparted格式化并重建分区
# 挂载efi分区和系统分区
mount /dev/nvmexxx /xxx
mount /dev/nvmexxx /xxx/boot/efi
cd /xxx
mount -t proc /proc proc
mount --rbind /sys sys
mount --rbind /dev dev
chroot /xxx
# 更新efi分区UUID(格式化后改变)
vim /etc/fstab
update-grub
grub-install
发现在 chroot 系统里也无法运行depmod, modeprobe
等命令,提示我安装zmod
,但是安装时又告诉我已经安装了。(这里又再次反映了问题所在)
重建 efi 分区后依然还是卡在紧急模式。
尝试,grub recovery 模式¶
修改 grub 配置后,可以进入 grub 菜单了。 我尝试 grub 选择旧的内核的 recovery 模式,但是却很不稳定,几乎立刻又会进入紧急模式,导致无法运行文字菜单中。
解决,kmod 不翼而飞¶
和 czw 讨论,复盘了下整个过程,并终于发现问题所在:
无法挂载 efi 分区 <- iso8895 错误 <- nls_iso8895-1.ko 不存在 <- find /lib/module/自己编译的内核/,发现ko文件是存在的。 modprobe 命令无法运行 <- 发现 modprobe 是一个链接指向/bin/kmod,并且是红色的,表示链接是无效的。 <- 发现/bin/kmod 文件不存在!
于是从 czw 的机器上拷贝了一份 kmod 文件,结果恢复模式可以进入了,机器也可以正常启动。
- p.s 发现 lxc zfs pool 又损坏了
总结¶
linux 启动过程¶
Arch boot process - ArchWiki (archlinux.org) Understanding the Boot process — BIOS vs UEFI (linuxhint.com)
OS 启动过程:
- 固件:CPU 最开始执行的指令。主要工作 POST 自检,硬件初始化,加载引导程序
- 引导程序:加载 os 内核(可以指定内核参数、初始文件系统)
- 内核:
- 初始化,如硬件初始化,驱动加载
- init:用户空间初始化。1-6 不同 run level,如 level 1 为 single user,level 3 为多用户命令行,level 5 包含图形化界面
- p.s level 6 为 reboot
BIOS
- BIOS,位于主板 flash
- 一级引导程序,位于 MBR,几百字节,非常小,用于加载二级引导程序
- 二级引导程序(grub),位于
- 内核,linux 内核 (vmlinuz) 位于系统盘/boot 路径下,有不同版本。该路径同时还有初始文件系统 (initrd.img)
UEFI
- UEFI,位于主板 flash
-
EFI 应用(grub),位于 ESP 分区(通常为 FAT32 文件系统)。grub image 在/boot/grub
各种救援模式¶
grub rescue¶
- 内核还没加载前,gurb 错误。如无法读取配置文件,需要手动指定 kernel 位置(哪个磁盘,哪个分区)
- grub 其它:
- 按 ESC 进入命令行模式,输入 normal 重回菜单界面。
- 菜单界面输入 e,可以编辑启动项。
- 选择 Ubuntu Advance,可以选择不同 kernel 版本,或者进入 recovery 模式
recovery 模式¶
- 将以单用户模式 (single-user) 模式启动,是最低的 runlevel。
- 用途:
- 忘记 root 密码
- 其它模式可能无法进入系统,而可以进入 recovery 模式进行恢复,或者备份文件。
- 后面要介绍的两个模式,则是系统无法挂载,被迫进入的模式。
Busybox Initramfs¶
- 内核初始化过程中,检测到根文件系统损坏。(initramfs 在内核初始化到能够挂载根文件系统前使用,busybox 包含常用的命令)
- 通常 fsck 文件系统即可
emergency 模式¶
- 内核初始化过程中因为一些原因崩溃
- 以只读模式挂载文件系统
心得¶
- 折腾之前做好最坏的打算。比如这次在我进入不了系统后,我最坏的情况是将重要文件、配置拷贝出来,然后重新安装系统。期间我可以使用我的笔记本干活(因为我的 workspace 文件夹是搭建了自动同步的)。如果在我的系统崩掉期间,我啥都干不了,那我的心理压力是会非常大的。