Note
|
v2 版改版说明:
|
Important
|
请务必准备一个可以启动的 Fedora Workstation LiveCD,万一在下面的调整中出现任何错误,我们还有从 LiveCD 启动,并挂载硬盘 chroot 进行补救的操作。
|
Important
|
如果你阅读了第一版文章,且更新到了 Fedora 41,那么在 systemd-boot 引导后会出现 Error preparing initrd: not found,请使用下方的命令进行急救:
|
systemd-boot 是 systemd 推出的仅支持 UEFI 模式启动的 boot loader,相较于 grub,systemd-boot 的配置更简单,使用也更加方便,如果你的机器支持 UEFI 启动,且你的系统也仅需 UEFI 启动,那么可以考虑使用 systemd-boot 替换 grub。
Important
|
|
Note
|
若你打算在安装 Fedora 的时候直接使用 systemd-boot 作为引导程序,那么可以直接在安装盘的引导的
|
主要分以下几个步骤
-
安装相关的包
-
使用
bootctl
将 systemd-boot 的 .efi 文件注入 EFI 分区中 -
使用
kernel-install
为 systemd-boot 生成启动条目 -
让机器的 UEFI 加载 systemd-boot,并引导至操作系统
-
移除 grub 相关的程序和配置文件
需要注意的一些路径:
-
/boot,Fedora 将启动相关的信息(比如 grub 的 .efi 文件和配置信息)保存在一个独立的磁盘分区中,该分区就会被 Fedora 挂载在 /boot 分区下,默认情况下,该分区为磁盘的第二个分区,且其文件系统为 ext4
-
/boot/efi,该路径并非是 /boot 对应的磁盘分区的内容,而是 EFI 分区的挂载路径,它的文件系统为 EFI Filesystem(其实是 FAT32)
Important
|
实际操作前须知: |
dnf install --allowerasing sdubby
安装 sduddy 包会同时安装 systemd-boot-unsigned,并移除 grubby 包。
sdubby 包中有不少与 systemd-boot 相关的配置文件,而 systemd-boot-unsigned 包则包含了 systemd-boot 所需的 efi 文件。
Important
|
在这一步之后, |
bootctl install
该操作将会在 /boot/efi 中释放相关的文件,主要是将 sysstemd-bootx64.efi 拷贝至 /boot/efi/EFI/systemd/ 下,并用相同的文件覆盖了 /boot/efi/EFI/BOOT/BBOTX64.efi;并在 EFI 自己的 NVRAM 里写入 systemd-boot 对应的启动项配置,我们可以通过 efibootmgr
命令观察到名为 Linux Boot Manager
的启动项。
之后我们就可以通过下面的命令查看可以由 systemd-boot 引导的系统:
bootctl list
给出的信息会有各种报错,这是因为系统上默认的配置文件并不符合 systemd-boot 的配置要求,因此我们还需要使用其它工具生成正确的配置。
在重启之后,我们再次使用 bootctl stataus
命令,就可以看到其输出中有
Current Boot Loader:
Product: systemd-boot XXX
字样,就表示本次启动是通过 systemd-boot 引导的了。
不过我们在启动过程中,应该没有看到任何的启动菜单界面,这个并不符合我们的要求,因此我们还需要再做一些配置,让启动菜单显示出来。
修改 /boot/efi/loader/loader.conf 文件,将 timeout 3
这行前的注释去掉,然后保存文件。再次重启,就能看到 systemd-boot 的启动菜单界面了。
其实到这一步,我们的系统就已经是 systemd-boot 引导的了,我们就可以着手删除 grub 相关的程序和配置了
Important
|
请再次确认系统可以正确被 systemd-boot 引导,否则我们在删除 grub 之后,可能会造成引导失败 |
Note
|
在这个步骤中,我们将
|
-
为 sdubby 和 systemd-boot-unsigned 包添加保护
在 /etc/dnf/protected.d/ 下添加文件 systemd-boot.conf,并在其中写入下面的内容/etc/dnf/protected.d/systemd-boot.confsdubby systemd-boot-unsigned
-
测试 sdubby 和 systemd-boot-unsigned 是否被保护成功
dnf remove --setopt=tsflags=test sdubby systemd-boot-unsigned
如果返回错误表示要移除的是 protected packages 则表示保护成功
-
移除 dnf 中 grub2、shim 包相关的保护
rm -f /etc/dnf/protected.d/grub2-*.conf /etc/dnf/protected.d/shim.conf
-
移除 grub 和 shim 相关的包
Important执行移除之后,切勿关机,此时系统缺失 /boot/efi/BOOT/BOOTX64.EFI 这个文件,会无法自动引导操作系统
如果此时不幸系统掉电,则请在机器启动时,进入 UEFI Shell,然后通过 FS0: 进入第一个文件系统,然后 EFI\systemd\systemd-bootx64.efi 启动系统dnf remove grub* shim* mactel-boot
注:我的电脑不是 mac,因此我还移除了引导 mac 相关的 mactel-boot 包
-
备份可能需要的文件
mkdir ~/boot_bk mv config* symvers* System.map* .vmlinuz* ~/boot_bk
-
卸载 EFI 分区和 /boot 对应的分区
umount /boot/efi /boot
-
准备 /boot 和 /boot/efi 文件夹
# 新建 /boot/efi,作为 EFI 分区的新挂载点 mkdir /boot/efi # 还原我们备份的文件 mv ~/boot_bk/* ~/boot_bk/.* /boot # 若你启用了 SELinux,这里还可以还原一下 /boot 整个目录的 SELinux 上下文 restorecon -v -R /boot # 还可以进一步还原 SELinux 上下文 chcon --recursive --verbose --user system_u /boot
-
删除 BOOT 分区,并调整 EFI 分区的大小
-
用 gdisk 删除 BOOT 分区和 EFI 分区
-
创建新的 EFI 分区,其分区类型的编号为
EF00
-
-
新建 EFI 分区的 vfat 文件系统
mkfs.vfat /dev/sda1
-
修改 /etc/fstab
-
用
lsblk -o+UUID
确认 EFI 分区的文件系统的 UUID -
从 /etc/fstab 中删除 BOOT 分区的挂载配置,并将 EFI 分区的文件系统的 UUID 修改为与
lsblk
返回的一致。
-
-
尝试挂载 /boot/efi
# systemd 似乎接管了 mount 的工作 systemctl daemon-reload mount /boot/efi
-
再次重建整个 EFI 分区的内容
# 移除残余的 Boot 启动项 bootctl remove # 新建 systemd-boot 引导程序 bootctl install # 重新生成可引导内核和 initrd kernel-install --verbose add-all
-
在重启电脑前,做最后的检查
-
lsblk -o+PARTUUID
返回的 EFI 分区的 PARTUUID 与efibootmgr
中启动项的磁盘的 PARTUUID 一致 -
lsblk -o+UUID
返回的 EFI 分区的文件系统的 UUID 与 /etc/fstab 中记录的一致 -
bootctl list
中返回的可引导条目的内容无误 -
当然,由于我们重建了整个 EFI 分区,我们还可以继续调整 /boot/efi/loader/lodaer.conf 中的配置
-
-
重启电脑
-
使用
efibootmgr
检查是否有残余的 EFI 启动项,如果有,用efibootmgr --bootnum <要删除的启动项编号> --delete-bootnum
清除
到此,我们就完成了使用 systemd-boot 作为唯一 boot loader 的流程
一般来说,是由于在启动菜单中设置了 timeout,或者通过 bootctl set-timeout
导致的
这两个方法会直接将 timeout 设置到 EFI 专有的 NVRAM 中,而且 NVRAM 中的值的优先度是高于 loader.conf 配置文件的
因此我们有两种方案解决这个问题
-
直接在 systemd-boot 启动菜单中按减号键
-
,直到屏幕上显示 Menu timeout defined by configuration file. -
删除 /sys/firmware/efi/efivars/LoaderConfigTimeout-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f 这个 EFI 变量
删除前需要用chattr -i
移除该文件的删除保护-
4a67b082-0a4c-41cf-b6c7-440b29bb8c4f 这个 UUID 是 systemd-boot 专属的 vendor UUID,见 The Boot Loader Interface
-
systemd 使用命令 kernel-install
来向 EFI/BOOT 分区注入可引导内核和相关信息,且 kernel-install 具有 systemd-boot 的配置文件。
kernel-install 的插件会读取 /etc/kernel/cmdline 来为 Linux kernel 添加命令行参数。因此我们可以修改 /etc/kernel/cmdline 的内容,并调用 kernel-install
来生成新的启动配置。
/etc/kernel/cmdline 中就是要传递给 kernel 的参数文本,因此我们直接进行修改即可
之后我们执行 kernel-install add-all
让 kernel-install 查找系统上存在的所有内核,并重新生成所有的启动条目。
Note
|
kernel-install 二进制程序更像流程的前端处理器,它负责收集来自命令行和系统的信息,并呈递给插件(脚本)来处理实际的问题。 |