From Fedora Project Wiki

介绍

GRUB 2 是 GNU GRUB (GRand Unified Bootloader) 的最新版本。bootloader(引导程序) 是计算机开机时第一个运行的软件程序。它负责加载操作系统内核并把控制权交给操作系统内核(Fedora 下就是 Linux 了)。反过来,内核初始化操作系统的其余部分。

GRUB 2 已经取代了之前的 GRUB (即,0.9x 版本),使 GRUB 成为了 GRUB Legacy 。

从 Fedora 16 开始,GRUB 2 就是 x86 BIOS 系统下默认的引导程序了。对于 BIOS 系统的升级也是默认安装 GRUB 2,但是您完全可以选择跳过配置引导程序。

使用 Grubby 管理内核引导参数

Grubby 可用于更新引导相关的配置文件,我们推荐你使用它更新内核引导参数和设定默认内核。

下面我们简单介绍 grubby 的用法:

  • 为单个引导项添加一个内核参数:
# grubby --args=<NEW_PARAMETER> --update-kernel=/boot/vmlinuz-5.11.14-300.fc34.x86_64
  • 为单个引导项添加多个内核参数:
# grubby --args="<NEW_PARAMETER1> <NEW_PARAMETER2 <NEW_PARAMETER_n>" --update-kernel=/boot/vmlinuz-5.11.14-300.fc34.x86_64
  • 为所有引导项添加内核参数:
# grubby --args=<NEW_PARAMETER> --update-kernel=ALL
  • 从当前和以后的所有引导项中删除内核参数:
# grubby --remove-args=<PARAMETER_TO_REMOVE> --update-kernel=ALL
  • 设置默认内核:
# grubby --set-default=/boot/vmlinuz-5.11.12-300.fc34.x86_64

更新 GRUB 2 主配置文件

/boot/grub2/grub.cfg 是默认的 GRUB 配置文件。通常来说你不需要去改动这个静态文件,除非你对磁盘进行了更换或并行安装了其他系统。

探测使用中的固件

执行下面的命令:

  • 在 UEFI 系统:
# ls -ld /sys/firmware/efi
  • 在 BIOS 系统:
# ls -lrt /etc/grub2.cfg

输出的结果即为你使用的固件。

grub2-mkconfig -o /boot/grub2/grub.cfg 将探测其他的操作系统并更新引导选单,这是通过 os-prober 实现的。

Note.png
使用 Fedora 32 或更早版本的用户可能需要使用 grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg.

修复 GRUB 2

如果你的系统无法引导,尝试进入恢复模式以对引导进行修复,详见 Fedora Docs 的相关文章

然后,执行下面的命令挂载根分区:

# chroot /mnt/sysimage

重新安装 GRUB 2

GRUB 2 软件包包含了安装引导器和生成 grub.cfg 配置文件的相关脚本。

grub2-install 会在 MBR 安装引导器,引导器的相关文件会储存在 /boot/ 目录。

要重装 GRUB 2:

  • 在 UEFI 系统:
# dnf reinstall shim-* grub-efi-*
  • 在 BIOS 系统:
    • 查看 /boot/ 目录位于哪个分区上:
# mount | grep "/boot "
/dev/sda4 on /boot type ext4 (rw,relatime,seclabel)

就如上面的例子,目录位于 /dev/sda4.

    • 重新安装引导器:
# grub2-install /dev/sda
Installing for i386-pc platform.
Installation finished. No error reported.
Warning.png
Do not use the grub2-install command on UEFI systems. On those systems, bootloaders are in the shim and grub-efi packages. By reinstalling those packages, the bootloaders are reinstalled to their proper location in /boot/efi/ (the EFI system partition).

Appendix

Enabling serial console in GRUB 2

To enable serial console for usage on virtual environments you need to run the following command:

# grubby --args="systemd.journald.forward_to_console=1 console=ttyS0,38400 console=tty1" --update-kernel=/boot/vmlinuz-5.11.16-300.fc34.x86_64
# grubby --set-default=/boot/vmlinuz-5.11.16-300.fc34.x86_64

The first command specifies the baud rate, console forwarding for systemd, what console to use (tty1) and on what kernel such changes should be applied. The second command ensures the specified kernel is going to be loaded by default on next reboot.

For instructions on how to enable serial consol in GRUB 2 for baremetal machines, see Using GRUB via a serial line.

In UEFI boot environment, use efi0 instead of --unit=0. If it does not work, check that your serial port is visible in your UEFI environment, e.g. by running devtree or dh -p SerialIO in EFI Shell. See Grub2 UEFI boot and serial console output for more information.

Fixing a damaged GRUB 2 configuration file using a plaintext stub file

On Fedora 34 and later, you can repair a malfunctioning grub.cfg configuration file by creating a stub file with the following content.

  1. Discover the Universally Unique Identifier (UUID) for the /boot/ mount point:
# lsblk --fs
NAME   FSTYPE  FSVER            LABEL                 UUID                                 FSAVAIL FSUSE% MOUNTPOINT
sr0    iso9660 Joliet Extension Fedora-WS-Live-34-1-2 2021-04-23-11-17-40-00                     0   100% /run/media/jdoe/Fedora-WS-Live-34-1-2
zram0                                                                                                     [SWAP]
vda                                                                                                       
├─vda1 ext4    1.0                                    dc29837b-22dc-4469-be85-fc9acf3009fd  699.8M    21% /boot
└─vda2 btrfs                    fedora_localhost-live c58f3698-5587-40f2-b920-64d46c43161d   23.7G    14% /home

The UUID of /boot/ is dc29837b-22dc-4469-be85-fc9acf3009fd.

  1. Create a custom grub.cfg file with the following content:
search --no-floppy --fs-uuid --set=dev dc29837b-22dc-4469-be85-fc9acf3009fd
set prefix=($dev)/grub2

export $prefix
configfile $prefix/grub.cfg

At the end of first line (--set=dev), there is the UUID value of the /boot/ mount point.

The above example assumes default partitioning, where a separate ext4 file system is mounted at /boot/. In case of other configurations, you need to insert /boot/ into line 2. For example:

...
set prefix=($dev)/boot/grub2
...
  1. Move or copy the custom grub.cfg file you created in the previous step to /boot/efi/EFI/fedora/grub.cfg

Setting default entry

Warning.png
Look to (default) kernel sysconfig options.
if file /etc/sysconfig/kernel have
UPDATEDEFAULT=yes
in every kernel update the grub entry is update to last entry, if you don't want that set:
UPDATEDEFAULT=no
(write "no" in lower case)
Warning.png
Some parts of this section is wrong or outdated for F17 and later releases.
Be also aware of [Bug 768106 - grubby does not support grub2 set default="${saved_entry}" and replaces with "0"]. version grubby-8.28-1.fc19 has fixed issues with "Default Menuentry" as noted in the linked bug-report

Due to grub2-mkconfig (and os-prober) we cannot predict the order of the entries in /boot/grub2/grub.cfg, so we set the default by name/title instead.

Open /etc/default/grub and ensure this line exists:

GRUB_DEFAULT=saved

and ensure this line not exists:

GRUB_SAVEDEFAULT=true

or ensure this line exists:

GRUB_SAVEDEFAULT=false
Note.png
Note
If GRUB_SAVEDEFAULT is set to true, then, when an entry is selected, save it as a new default entry for use by future runs of GRUB. So, maybe, you need be sure that GRUB_SAVEDEFAULT is not set to true. GRUB_SAVEDEFAULT is only useful if GRUB_DEFAULT is saved.

Apply the change to grub.cfg by running:

grub2-mkconfig -o /boot/grub2/grub.cfg

Now list all possible menu entries

grep -P "submenu|^menuentry" /boot/grub2/grub.cfg | cut -d "'" -f2

Now set the desired default menu entry

grub2-set-default "<submenu title><menu entry title>"

Verify the default menu entry

grub2-editenv list
Note.png
Note
The above method fails to work on some F20 (and newer) systems due to a missing or improperly linked /boot/grub2/grubenv file. The /boot/grub2/grubenv is symbolic linked to /boot/efi/EFI/fedora/grubenv but /boot is not mounted at the time of booting. So grub2 does not have access to the environment variables. To fix this, change /boot/grub2/grubenv to point to ../efi/EFI/fedora/grubenv instead and your chosen default OS will boot without any problems.
Note.png
Note
There are other, simpler, ways of setting the default entry, but they are prone to error if/when grub2-mkconfig is re-run. These include directly setting the default in /boot/grub2/grub.cfg or setting GRUB_DEFAULT to either a number or an entry title in /etc/default/grub. Neither of these methods is recommended.

If you understand the risks involved and still want to directly modify /boot/grub2/grub.cfg, here's how you can do it:

Edit /boot/grub2/grub.cfg, and change the line

Stop (medium size).png
This is not the recommended method
This will not survive grub2-mkconfig. It might not even survive a kernel update.
set default="0" 

to

set default="5"

深入阅读

http://www.gnu.org/software/grub/manual/grub.html

http://fedoraproject.org/wiki/Features/Grub2

http://fedoraproject.org/wiki/Anaconda/Features/Grub2Migration