linux引导修复记_2025.9.4

前言

  系统引导故障虽不频发,但折腾得多了,小概率事件也难免出现。
  虽然,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的情况。这就不在本文的考虑范围内了。

1 个赞

:hibiscus: