GRUB
GRUB 来自 GRand Unified Bootloader 的缩写。它的功能是在启动时从 BIOS 接管掌控、载入自身、载入 Linux 核心到内存,然后再把执行权交给核心。一旦核心开始掌控,GRUB 就完成了它的任务,也就不再需要了。
GRUB 支援多种 Linux 核心,并允许使用者在启动时通过选单在其中选择。我发现这是一种非常有用的工具,因为我有很多次遇到一个应用程式或者系统服务在特定核心版本下失败的问题。有好几次,引导到一个较旧的核心时就可以避免类似的问题。预设情况下,使用 yum 或 dnf 进行更新时会储存三个核心 – 最新的以及两个比较旧的。在被包管理器删除之前所保留的核心数目可以在 /etc/dnf/dnf.conf 或 /etc/yum.conf 档案中配置。我通常把 installonly_limit 的值修改为 9 以便保留 9 个核心。当我不得不恢复到低几个版本的核心时这非常有用。
GRUB 选单
GRUB 选单的功能是当预设的核心不是想要的时,允许使用者从已经安装的核心中选择一个进行引导。通过上下箭头键允许你选中想要的核心,敲击回车键会使用选中的核心继续引导程序。
GRUB 选单也提供了超时机制,因此如果使用者没有做任何选择,GRUB 就会在没有使用者干预的情况下使用预设核心继续引导。敲击键盘上除了回车键之外的任何键会停止终端上显示的倒数计时器。立即敲击回车键会使用预设核心或者选中的核心继续引导程序。
GRUB 选单提供了一个 “救援 rescue” 核心,用于故障排除或者由于某些原因导致的常规核心不能完成启动过程。不幸的是,这个救援核心不会引导到救援模式。文章后面会更详细介绍这方面的东西。
grub.cfg 档案
grub.cfg 档案是 GRUB 配置档案。它由 grub2-mkconfig 程式根据使用者的配置使用一组主配置档案以及 grub 预设档案而生成。/boot/grub2/grub.cfg 档案在 Linux 安装时会初次生成,安装新核心时又会重新生成。
grub.cfg 档案包括了类似 Bash 指令码的程式码以及一个按照安装顺序排序的已安装核心列表。例如,如果你有 4 个已安装核心,最新的核心索引是 0,前一个核心索引是 1,最旧的核心索引是 3 。如果你能访问 grub.cfg 档案,你应该去看看感受一下它看起来是什么样。 grub.cfg 太大也就没有包含在这篇文章中。
GRUB 配置档案
grub.cfg 的主要配置档案都在 /etc/grub.d 目录。该目录中的每个档案都包含了最终会整合到 grub.cfg 档案中的 GRUB 程式码。这些配置档案的命名模式以排序方式设计,这使得最终的 grub.cfg 档案可以按正确的顺序整合而成。每个档案都有注释表明该部分的开始和结束,这些注释也是最终的 grub.cfg 档案的一部分,从而可以看出每个部分是由哪个档案生成。分隔注释看起来像这样:

### BEGIN /etc/grub.d/10_linux ###
### END /etc/grub.d/10_linux ###

不要修改这些档案,除非你是一个 GRUB 专家并明白更改会发生什么。无论如何,修改 grub.cfg 档案时你也总应该保留一个原始档案的备份。 40_custom 和 41_custom 这两个特别的档案用于生成使用者对 GRUB 配置的修改。你仍然要注意对这些档案的更改的后果,并储存一份原始 grub.cfg 档案的备份。
你也可以把你自己的档案新增到 /etc/grub.d 目录。这样做的一个可能的原因是为非 Linux 操作系统新增选单行。要注意遵循命名规则,确保配置档案中额外的选单选项刚好在 10_linux 条目之前或之后。
GRUB 预设档案
老版本 GRUB 的配置非常简单而明了,我只需要修改 /boot/grub/grub.conf 就可以了。对于新版本的 GRUB2,我虽然还可以通过更改 /boot/grub2/grub.cfg 来修改,但和老版本的 GRUB 相比,新版本相对更加复杂。另外,安装一个新核心时 grub.cfg 可能会被重写,因此任何修改都可能消失。当然,GNU.org 的 GRUB 手册确实有过直接建立和修改 /boot/grub2/grub.cfg 的讨论。
一旦你明白了如何做,更改 GRUB2 配置就会变得非常简单。我为之前的文章研究 GRUB2 的时候才明白这个。秘方就在 /etc/default 目录里面,一个自然而然称为 grub 的档案,它可以通过简单的终端命令操作。/etc/default 目录包括了一些类似 Google Chrome 、 useradd 、 和 grub 程式的配置档案。
/etc/default/grub 档案非常简单。这个 grub 预设档案已经列出了一些有效的键值对。你可以简单地更改现有键值或者新增其它档案中还没有的键。下面的列表 1 显示了一个没有更改过的 /etc/default/grub 档案。

GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR=”$(sed ‘s, release .*$,,g’
   /etc/system-release)”
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT=“console”
GRUB_CMDLINE_LINUX=”rd.lvm.lv=fedora_fedora25vm/root
   rd.lvm.lv=fedora_fedora25vm/swap
   rd.lvm.lv=fedora_fedora25vm/usr rhgb quiet”
GRUB_DISABLE_RECOVERY=“true”

列表 1:Fedora 25 一个原始 grub 预设档案。
GRUB 手册 5.1 章节包括了所有可以新增到该 grub 档案的键的资讯。我只需要修改 grub 预设档案已经有的一些键值就够了。让我们看看这些键值以及一些在 grub 预设档案中没有出现的每个键的意义。

GRUB_TIMEOUT 这个键的值决定了显示 GRUB 选择选单的时间长度。 GRUB 提供了同时储存多个安装核心并在启动时使用 GRUB 选单在其中选择的功能。这个键的预设值是 5 秒,但我通常修改为 10 秒使得有更多时间检视选项并作出选择。
GRUB_DISTRIBUTOR 这个键定义了一个从 /etc/system-release 档案中提取发行版本的 sed 表示式。这个资讯用于生成出现在 GRUB 选单中的每个核心释出版的文字名称,例如 “Fedora” 等。由于不同发行版之间 system-release 档案结构的差异,在你的系统中这个 sed 表示式可能有些不同。
GRUB_DEFAULT 决定预设引导哪个核心。如果是 saved,这代表最新核心。这里的其它选项如果是数字则代表了 grub.cfg 中列表的索引。使用索引号 3,就会总是载入列表中的第四个核心,即使安装了一个新核心之后也是。因此使用索引数字的话,在安装一个新核心后会载入不同的核心。要确保引导特定核心版本的唯一方法是设定 GRUB_DEFAULT 的值为想要核心的名称,例如 4.8.13-300.fc25.x86_64 。
GRUB_SAVEDEFAULT 通常,grub 预设档案中不会指定这个选项。当选择不同核心进行引导时,正常操作下该核心只会启动一次。预设核心不会改变。当其设定为 true 并和 GRUB_DEFAULT=saved 一起使用时,这个选项会储存一个不同核心作为预设值。当选择不同核心进行引导时会发生这种情况。
GRUB_DISABLE_SUBMENU 一些人可能会希望为 GRUB 选单建立一个核心的层级选单结构。这个键和 grub.cfg 中一些额外核心配置允许建立这样的层级结构。例如,主选单中可能有 production 和 test 子选单,每个子选单中包括了一些合适的核心。设定它为 false 可以启用子选单。
GRUB_TERMINAL_OUTPUT 一些环境下可能需要或者必要将输出重定向到一个不同的显示控制台或者终端。预设情况下是把输出传送到预设终端,通常 console 等价于 Intel 系列个人电脑的标准输出。另一个有用的选择是在使用序列终端或者 Integrated Lights Out (ILO) 终端连线的资料中心或者实验室环境中指定 serial 。
GRUB_TERMINAL_INPUT 和 GRUB_TERMINAL_OUTPUT 类似,可能需要或者必要重定向输入为序列终端或者 ILO 装置、而不是标准键盘输入。
GRUB_CMDLINE_LINUX 这个键包括了在启动时会传递给核心的命令列引数。注意这些引数会被新增到 grub.cfg 所有已安装核心的核心行。这意味著所有已安装的核心在启动时都会有相同的引数。我通常删除 rhgb 和 quiet 引数以便我可以看到引导和启动时核心和 systemd 输出的所有核心资讯讯息。
GRUB_DISABLE_RECOVERY 当这个键的值被设定为 false,GRUB 选单中就会为每个已安装的核心建立一个恢复条目。当设定为 true 时就不会建立任何恢复条目。但不管这个设定怎样,最后的核心条目总是一个 rescue 选项。不过在 rescue 选项中我遇到了一个问题,下面我会详细介绍。

还有一些你可能觉得有用但我没有在这里介绍的键。它们的描述可以在 GRUB 手册 2 的 5.1 章节找到。
生成 grub.cfg
完成所需的配置之后,就需要生成 /boot/grub2/grub.cfg 档案。这通过下面的命令完成。

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

这个命令按照顺序使用位于 /etc/grub.d 的配置档案构建 grub.cfg 档案,然后使用 grub 预设档案的内容修改输出以便获得最终所需的配置。 grub2-mkconfig 命令会尝试定位所有已安装的核心并在 grub.cfg 档案的 10_Linux 部分新建条目。它还建立一个 rescue 条目提供一个用于从 Linux 不能启动的严重问题中恢复的方法。
强烈建议你不要手动编辑 grub.cfg 档案,因为任何对该档案的直接修改都会在下一次安装新核心或者手动执行 grub2-mkconfig 时被重写。
问题
我遇到一个如果没有意识到就可能导致严重后果的 GRUB2 问题。这个救援核心没有启动,反而启动了另外一个核心。我发现那是列表中索引为 1 的核心,也就是列表中的第二个核心。额外的测试发现不管使用原始的还是我生成的 grub.cfg 配置档案都会发生这个问题。我在虚拟机器和真实硬体上都尝试过而且都发生了这个问题。我只测试了 Fedora 25,因此其它 Fedora 发行版本可能没有这个问题。
注意,从救援核心生成的 “recovery” 核心条目不能引导到维护模式。
我推荐将 grub 预设档案中 GRUB_DISABLE_RECOVERY 的值更改为 “false”,然后生成你自己的 grub.cfg 。这会在 GRUB 选单中为每个已安装的核心生成可用的恢复条目。这些恢复配置能像期望那样工作,从而从那些需要输入密码登入的核心条目中引导到执行级别 1,也就是进入 (不需要密码的) 单使用者维护模式。你也可以按 Ctrl-D 继续正常的引导进入预设执行级别。
总结
GRUB 是引导 Linux 计算机到可用状态过程的一系列事件中,发生在 BIOS 之后的第一步。理解如何配置 GRUB 对于恢复或者处理多种型别的问题非常重要。
这么多年来我多次不得不引导到恢复或者救援模式以便解决多种型别的问题。其中的一些问题确实是类似 /etc/fstab 或其它配置档案中不恰当条目导致的引导问题,也有一些是由于应用程式或者系统站群软件和最新的核心不相容的问题。硬体相容性问题也可能妨碍特定的核心启动。