前言
系统引导故障虽不频发,但折腾得多了,小概率事件也难免出现。
虽然,ventoy多启动U盘在手,系统安装不过举手之劳,因此,当系统故障时,往往重装远比修复来得容易。不过,偶尔探索一下,权当学习,也是不错的。
比较有趣的是,这次的故障情况足够多,以致于可以记录一个足够有参考价值的教程了。
本教程解决的核心问题:
- 修复因EFI分区配置错误导致的引导丢失
- 重建UEFI启动项
- 修复fstab导致的启动失败
故障原因
由于一些有趣的原因,上头不让使用国产系统。于是,我尝试将OpenKylin安装在我的U盘上。
然而,U盘系统虽好,天天996,U盘有些带不动了。
于是又改一个方案,挪一挪电脑磁盘的分区,从安装有Win11的256G硬盘里,再抠抠索索省出89G的空间,拿来安装开放麒麟系统(OpenKylin)。希望达到的效果是,开机无提示默认进入Win11系统(不经过grub),掩人耳目。自用时,通过开机时按F8(或F12等)键,从BIOS的引导选择中,可以自主选择OpenKylin的引导项,进入OpenKylin系统。
本来,这不是什么难事。群友普遍认为OpenKylin2.0sp2还有点欠优化,暂不适合作为办公用的系统。那就继续2.0sp1好了。从U盘启动,选择进入开放麒麟liveCD(即镜像文件,是一个可直接运行的操作系统),安装开放麒麟系统,安装时,设置EFI分区为/boot/efi挂载点,将未分配的空间设置为新系统的分区,即/ 挂载点,其余挂载点一律省略。安装完毕,重启即可。
偏偏我脑子一抽,安装系统时,将另一个U盘的一个分区设置为系统的EFI分区,并用作/boot/efi挂载点。我以为这样能把OpenKylin系统藏得更好。事实证明,确实藏得好。
原以为问题不大。甚至尝试用微PE工具中的DiskGenius,把openkylin的efi文件,强行塞到电脑的efi分区,然而,毫无作用,徒增后期修复的步骤,果然,无知时不要盲目努力。
还是面向AI学习吧。后续教程皆改编自腾讯元宝的回复。
一、重建引导文件
第一阶段:准备工具
1. 启动到 OpenKylin Live USB 环境
2. 打开终端,获取 root 权限:
sudo -i
第二阶段:检查和分析分区情况
1.查看磁盘分区信息:
fdisk -l
#或使用更详细的工具:
parted -l
2. 识别关键分区:
•EFI 系统分区 (ESP):通常是较小的 FAT32 分区 (100MB-500MB)
•OpenKylin 根分区:通常是较大的 ext4 分区
这里,我的分区情况是:
•ESP: /dev/sda1
•OpenKylin: /dev/sda5
注意,读者可参考本文的后续代码,但不同电脑的分区代码不同,需要自行修改。
第三阶段:开始重建引导文件
步骤 1:挂载分区
# 创建挂载点
mkdir -p /mnt/linux
mkdir -p /mnt/efi
# 挂载分区,这里,至少要挂载根(/)和efi两个分区。
# 若安装系统时还设置了其他分区,也要合理挂载
mount /dev/sda5 /mnt/linux # OpenKylin 根分区,根据自己的分区修改sdaX
mount /dev/sda1 /mnt/efi # EFI 系统分区
步骤 2:检查 ESP 分区状态
# 检查efi文件系统,通常无大问题,若有可自行搜索学习
fsck -y /dev/sda1
# 查看 ESP 分区内容
ls -la /mnt/efi/EFI/
目前的ESP 分区应该没有openkylin的efi,需要生成。
步骤 3:重新安装 openkylin的efi
# 挂载必要的系统目录
mount --bind /dev /mnt/linux/dev
mount --bind /proc /mnt/linux/proc
mount --bind /sys /mnt/linux/sys
mount --bind /run /mnt/linux/run
# 因为要切换到sda5分区的openkylin系统,所以要再次挂载 ESP 分区(即efi分区)
# 若安装系统时还设置了其他分区,也要合理挂载
mkdir -p /mnt/linux/boot/efi
mount /dev/sda1 /mnt/linux/boot/efi
# 切换到分区中的系统环境
chroot /mnt/linux
# 完全重新安装 GRUB
# 随后efi分区中,将出现有系统的引导文件/EFI/openkylin/grubx64.efi
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=openkylin --recheck
# 更新 GRUB 配置,grub会自动识别硬盘其他分区中的系统,并加入grub引导
update-grub
#取消efi分区挂载
umount /mnt/linux/boot/efi
# 退出 chroot,回到live USB环境
exit
# 解除挂载
sudo umount /mnt/{dev,proc,sys,run}
sudo umount /mnt/linux
sudo umount /mnt/efi
遇到的问题
事实上,这一步耗时许久,又重复了几次,但并未能修复系统。究其原因,其一,前面手动用微PE工具中的DiskGenius,强行改动过efi分区,于是检查efi文件系统时,程序检查到错误,只好复制给AI求解;其二,AI并非万能,给出的代码有时也存在有错误,需要自己有基本的判断力,进行修正或再度向AI提问;其三,也是最主要的,自己的知识有限,对原理不甚了解,其实,这一步的工作,核心是,在一个系统环境(Live USB)中,挂载另一个系统环境(磁盘中的系统),并切换到挂载的系统中,由它来工作,向磁盘的ESP分区中,注入一个引导它的efi文件。
但至此,仍未结束。我们还需要让硬件发现这个引导openkylin的efi文件,才能由硬件启动它。
二、启动项信息写入主板的NVRAM
这台电脑是 UEFI + GPT 的启动方式,所以重建了EFI文件后,还需要将启动项信息(一个指向EFI文件的“指针”)写入主板的NVRAM中,才能完成修复。
1. 安装 efibootmgr
sudo apt install efibootmgr
2. 使用 efibootmgr 创建启动项
# 使用 efibootmgr 创建启动项
efibootmgr -c -d /dev/sda -p 1 -L "OpenKylin" -l \\EFI\\openkylin\\grubx64.efi
#命令解析:
# 1.-c:创建新的启动项 (create)
# 2.-d /dev/sda:指定包含 EFI 系统分区(ESP)的磁盘设备
# 3.-p 1:指定 ESP 分区在该磁盘上的分区号
# 4.-L "OpenKylin":设置启动项在 BIOS/UEFI 菜单中显示的名称
# 5.-l \\EFI\\openkylin\\grubx64.efi:指定 EFI 引导文件的路径(相对于 ESP 分区根目录)
# 查看当前启动项,若有了“OpenKylin”,说明修复成功
efibootmgr -v
# 设置启动顺序,这一步我未在bash完成,改从bios设置中修改
三、进入系统
执行了这些操作后,确实有了openkylin的启动项。不过,一直无法进入系统。
便又打算直接重装算了,后来一想,会不会是/etc/fstab文件的问题呢?我修改了其中的内容后,正常地进入系统了。
这是我原来的/etc/fstab文件内容,可以看到,我为系统设置了两个分区,一个EFI分区(格式为vfat),设置为/boot/efi挂载点,一个ext4格式的分区,设置为根挂载点“/”。
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point> <type> <options> <dump> <pass>
# /dev/sda5
UUID=eaabe0fr-a3f2-4491-4656-3258rt03327e / ext4 rw,relatime 0 1
# /dev/sdb1
UUID=46R3-E452 /boot/efi vfat defaults,umask=0077 0 0
由于我最初安装系统时设置的EFI分区在另一个U盘,现在要改回电脑磁盘的ESP分区(sda1),因此,需要修改其中的“UUID= ****”内容。
通过命令 sudo blkid
,找到ESP分区对应的UUID号,复制下来。再sudo vi /etc/fstab
,借助vi编辑器,修改其中内容,就完成了最终的修复工作了。读者可自行搜索vi的语法,若不喜欢vi语法,在root权限下用Python完成也不是不行。
这个文件指定了系统的各挂载点,因此,我们还可以修改这个文件,让系统在启动的时候,自动挂载电脑磁盘的其他分区。
小结
修复完成后,成功地进入系统了。
不过,还是忍不住又问一下AI,这里的三步修复——修复引导文件(efi文件)、向硬件写入UEFI启动项、修复fstab文件,是否都是必须的?尤其第2步是我之前一直忽略的问题。
得到的答复是,前两步确实必须,但最后一步, 仅当分区UUID/挂载点错误时才需修复,例如:误用设备名(如/dev/sda1)而非UUID;ESP分区未正确指向/boot/efi;等等。
于是,积累了些许经验吧。嗯,以下是一些原理:
不同启动方式的原理有所不同,因此,修复方式也不太一样。
传统 BIOS/MBR 启动方式
这一类型是2010年前老电脑(是的,这些电脑确实是老电脑)的主流配置。MBR是磁盘分区类型,仅支持最多4个主分区(或3主分区+1扩展分区),支持的磁盘大小最多2TB;BIOS(基本输入输出系统),它是存储在主板上的一个固件,且是只读不可写的,它担负着初始化硬件,检测硬件功能以及引导操作系统的任务。对于这一类型,所有启动信息存储在磁盘固定位置(MBR和分区PBR),启动流程为:
(1)电源开启 → 主板BIOS初始化
(2)读取磁盘MBR → 执行主引导记录中的代码
(3)激活分区 → 加载分区引导记录(PBR)
(4)启动加载器 → 执行第二阶段的引导程序(如GRUB)
(5)启动操作系统 → 加载内核
现代 UEFI/GPT 启动方式
这一类型是当前主流,GPT是另一种磁盘分区类型,支持128个主分区,最大磁盘18EB;UEFI是一个统一的可扩展固件接口标准,主板厂商将UEFI标准实现为固件(存储在主板SPI闪存芯片中),用来启动系统,这样的启动方式,解决了BIOS的许多局限性。对于这一类型,启动信息存储在启动项信息存储在主板的NVRAM(非易失性存储器),引导文件存储在ESP分区(FAT32格式),其启动流程为:
(1)电源开启 → UEFI固件初始化
(2)读取NVRAM → 获取启动菜单中的EFI文件路径
(3)定位EFI文件 → 在EFI系统分区(ESP)中查找.efi引导文件
(4)执行引导程序 → 加载操作系统内核
(5)启动操作系统 → 完成系统引导
对应的修复方式
当遇到启动问题时,
(1)BIOS/MBR系统:借助bootrec或grub-install之类的工具,修复磁盘引导扇区,因为bios是不可写的,没有出问题的时候就不必修;
(2)UEFI/GPT系统:借助efibootmgr / bcdedit之类的工具,既要重建EFI文件,还要更新NVRAM启动项。
(3)鉴于人类的创造力无穷,其实也有用BIOS引导GPT,用UEFI引导MBR的情况。这就不在本文的考虑范围内了。