内容


学习 Linux,101

安装引导管理器

介绍 GRUB、GRUB 2 和 LILO

Comments

系列内容:

此内容是该系列 # 部分中的第 # 部分: 学习 Linux,101

敬请期待该系列的后续内容。

此内容是该系列的一部分:学习 Linux,101

敬请期待该系列的后续内容。

概述

在本教程中,将学习如何为 Linux 系统选择、安装和配置引导管理器。学习:

  • 提供备用引导位置和备份引导选项
  • 安装和配置引导加载程序,比如 GRUB Legacy
  • 对 GRUB 2 执行基本配置更改
  • 与引导加载程序交互

引导管理器

引导管理器引导加载程序 是代码的中间部分,它帮助系统的硬件和固件为您加载一个操作系统。本教程将讨论 PC 引导过程和 Linux 中使用的三个主要引导加载程序:GRUB、GRUB 2 和 MBR 格式磁盘中的 LILO。最初的 GRUB(现在称为 GRUB-Legacy)已不再得到积极开发,而且很大程度上已被较新的 GRUB 2 所取代。甚至 Red Hat Enterprise Linux 和 SUSE Linux Enterprise Server 等商业发行版也于 2014 年开始改用 Grub 2。Lilo 的开发预计将于 2015 年末终止。

本教程将帮助您针对 Linux Server Professional (LPIC-1) 考试 101 的主题 102 中的目标 102.2 进行应考准备。该目标的权重为 2。LPIC-1 不再要求学习 LILO。这里包含它是为了让您对它有所了解。

本教程将重点介绍使用传统 BIOS 以及具有主引导记录 (MBR) 的磁盘来实现引导。本文还将介绍可扩展统一固件接口 (UEFI) 及其相关 GUID 分区表 (GPT) 的一些基本知识,以及您可能在它们中发现的引导问题,尤其在您需要在单个系统上同时引导 Windows® 8 和 Linux 时。

前提条件

要从本系列教程中获得最大收获,您应该掌握 Linux 的基本知识,还应该有一个正常工作的 Linux 系统,您可以在这个系统上实践本教程中涵盖的命令。您还应该熟悉教程“学习 Linux 101:硬盘布局”中讨论的硬盘驱动器布局。有时候,程序的不同版本将获得不同的输出格式,所以您的结果可能并不总是与这里显示的清单和图完全相同。

备注:本教程中的图是在引导过程的早期截取的屏幕截图。如果使用一个屏幕阅读器来阅读本教程,您可能会发现拥有相应的配置文件作为参考对您很有帮助;可以从本教程后面的下载部分下载它们。

引导过程概述

在介绍具体的引导加载程序之前,让我们回顾一下传统 PC 是如何启动或引导的。名为 BIOS(表示 Basic Input Output Service,基本输入输出服务)的代码存储在 ROM、EEPROM 或闪存等非易失性存储器(non-volatile memory)中。打开或重新引导 PC 时,会执行此代码。通常,它会执行开机自检 (POST) 来检查机器。最后,它从硬盘驱动器上的主引导记录 (MBR) 加载第一个扇区。

正如教程“学习 Linux 101:硬盘布局”中所介绍的,MBR 还包含分区表,所以 MBR 中的可执行代码量少于 512 字节,没有太多的代码。每个磁盘(甚至是软盘)在其 MBR 中都包含可执行代码,即使该代码只够放入一条消息,比如“Non-bootable disk in drive A:(驱动器 A 中的不可引导磁盘:)”。BIOS 从第一个扇区加载的这段代码被称为第一阶段引导加载程序或阶段 1 引导加载程序。

MS DOS、PC DOS 和 Windows 操作系统所使用的标准硬盘驱动器 MBR 会检查分区表,查找引导驱动器上标为 active 的主分区,加载该分区的第一个扇区,并将控制权传递到已加载的代码的开始处。这段新代码也称为分区引导记录。分区引导记录实际上是另一个阶段 1 引导加载程序,但这个加载程序只能从分区加载一组数据块。这组新数据块中的代码被称为阶段 2 引导加载程序。在由 MS-DOS 和 PC-DOS 使用时,阶段 2 加载程序直接继续加载操作系统的其余部分。这就是操作系统在正常运行之前通过其引导程序启动自身的过程。

这适用于具有单个操作系统的系统。如果想要使用多个操作系统,比如 OS/2、Windows 7 和三个不同的 Linux 发行版,会发生什么?您可以 使用某个程序(比如 DOS FDISK 程序)来更改活动分区并重新引导。但这种方法比较笨拙。此外,一个磁盘最多只能有 4 个主分区,标准 MBR 只能有 1 个活动主分区;而且它无法从逻辑分区进行引导。但我们的假设示例提到了 5 种操作系统,每个系统都需要一个分区。天啦!

解决方案就是使用一些特殊代码以允许用户选择要引导哪个操作系统。示例包括:

Loadlin
一个 DOS 可执行程序,可从正在运行的 DOS 系统调用该程序来引导一个 Linux 分区。如果设置多引导 (multiboot) 系统是一个复杂的高风险过程,这个程序就可以 帮上大忙。
OS/2 Boot Manager
一个安装在小型专用分区中的程序。该分区被标记为 active,标准 MBR 引导过程会启动 OS/2 Boot Manager,它有一个菜单可供您选择引导哪个操作系统。
智能引导加载程序
一个可位于某个操作系统分区中的程序,通过活动分区的分区引导记录或主引导记录进行调用。示例包括:
  • BootMagic(包含在 Norton PartitionMagic 中)
  • LILO (LInux LOader)
  • GRUB (GRand Unified Boot loader)(现在称为 GRUB Legacy)
  • GRUB 2,目前在许多常见发行版中使用的新型引导加载程序
  • Syslinux,一组轻型引导加载程序,适用于 MS-DOS FAT 文件系统 (SYSLINUX)、网络引导 (PXELINUX)、“El Torito”可引导 CD-ROM (ISOLINUX),及 Linux ext2/ext3/ext4 或 btrfs 文件系统 (EXTLINUX)

很明显,如果可将系统控制权移交给某个拥有超过 512 字节代码的程序来完成其任务,那么从逻辑分区进行引导或从位于引导驱动器之外的分区进行引导应该不是很难。上述所有解决方案都支持这些可能性,这是因为它们都能从任意分区加载引导记录,或者因为它们都了解启动引导过程所要加载的具体文件。

链式加载

当一个引导管理器获得控制权时,它可以加载另一个引导管理器。这被称为链式加载,通常发生在位于主引导记录 (MBR) 中的引导管理器加载了位于分区引导记录中的引导加载程序时。在 Linux 引导加载程序被要求引导一个 Windows 或 DOS 分区时,几乎总是会执行这种链式加载,但在配置一个 Linux 系统(比如 Fedora)的 Linux 引导加载程序来加载另一个 Linux 系统(比如 Ubuntu)的引导加载程序时,也有可能执行此加载。例如,您可以使用一个分区中的 GRUB 来启动另一个分区的引导记录中的 GRUB 引导加载程序,以便启动该分区中的 Linux 系统。这种情况并不常见,但它说明存在这种可能性。

Linux 引导加载程序

本教程将重点介绍 GRUB、GRUB 2 和 LILO,因为这些是大多数 Linux 发行版中都会包含的引导加载程序。LILO 已存在一段时间了。GRUB 比较新。最初的 GRUB 现在已成为 GRUB Legacy,GRUB 2 是在自由软件基金会 (Free Software Foundation) 的赞助下开发的(参见参考资料了解详细信息)。本教程首先讨论 GRUB,然后讨论 GRUB 2,让您对它们的主要区别以及 GRUB 和 GRUB 2 如何共存有一定的了解。在本教程的剩余部分中,假设 GRUB 表示 GRUB Legacy,专门指出 GRUB 暗指 GRUB 2 的上下文除外。还提供了 LILO 的一个名为 ELILO 的新版本(它是为引导使用英特尔的可扩展固件接口 (EFI) 而不是 BIOS 的系统而设计的)。请参见参考资料,了解 ELILO 的更多信息。

前面已经提到过,GRUB Legacy 不再得到积极开发,LILO 的开发预计将于 2015 年末终止。大部分 2015 年的 Linux 系统都默认提供 GRUB 2,有时它是唯一的引导加载程序。

您的发行版的安装过程可能会让您选择要安装哪个引导加载程序。GRUB、GRUB 2 和 LILO 都适用于大部分现代磁盘,但一些发行版(最明显的是 Fedora)不再包含 LILO 或 GRUB Legacy。请记住,磁盘技术已获得了迅猛发展,所以您应始终确保您选择的引导加载程序、Linux 发行版(或其他操作系统)和您的系统 BIOS 将兼容您的新磁盘。如果做不到这一点,则有可能导致数据丢失。类似地,如果向现有系统添加一个新发行版,可能需要确保您的 MBR 中拥有最新的 LILO、GRUB 或 GRUB 2。如果计划从 LVM 或 RAID 磁盘进行引导,那么还需要提供您的引导加载程序的一个最新版本。

借助 LILO 和 GRUB 中使用的阶段 2 加载程序,您可以从多个可加载的操作系统或版本中进行选择。但是,LILO 和 GRUB 有很大的区别,因为只要升级了内核或对您的系统执行了其他更改,对系统的更改就会要求您使用命令来重新创建 LILO 引导设置,而 GRUB 可以通过您可以编辑的配置文本文件来完成此任务。GRUB 2 还要求从通常存储在 /etc 中的一个配置文件执行重新构建。

GRUB

GRUB(或 GRand Unified Boot 加载程序)长期以来一直是最常用的 Linux 引导加载程序之一。可以将 GRUB 安装到可引导硬盘驱动器的 MBR 中,或者将它安装到某个分区的分区引导记录中。您还可以将它安装在可移动设备上,比如软盘、CD 或 U 盘。如果还不熟悉 GRUB,那么在软盘或 U 盘上练习是一个好主意。本教程中的示例会向您展示如何做。

备注:教程中的大部分 GRUB 示例都使用了 CentOS 6。

在 Linux 安装期间,通常会指定您选择的引导管理器。 如果选择 LILO,那么您有可能没有安装 GRUB。如果没有安装 GRUB,而且它可以用于您的发行版,那么您需要安装适用于它的包。本教程假设您已经安装了 GRUB 包。如果需要帮助,请参阅教程的系列路线图来了解包管理。

GRUB (Legacy) 有一个配置文件,该文件通常存储在 /boot/grub/grub.conf 中。如果文件系统支持符号链接,像大多数 Linux 文件系统一样,您可以将 /boot/grub/menu.lst 作为 /boot/grub/grub.conf 的符号链接。

grub 命令(sbin/grub,在某些系统上是 /usr/sbin/grub)是一个较小但比较强大的 shell,它支持用于安装 GRUB、引导系统、找到和显示配置文件,以及执行类似任务的多个命令。这个 shell 的许多代码与第 2 阶段 GRUB 引导加载程序相同,所以它对学习 GRUB 很有用,这样您就无需引导至第 2 阶段 GRUB 环境。GRUB 第 2 阶段可以在菜单模式下或命令模式下运行,在菜单模式下,您可以从菜单中选择一个操作系统;在命令模式下,您可以指定各个命令来加载系统。还有其他一些命令(比如 grub-install),它们使用 grub shell 并帮助自动化一些任务,比如安装 GRUB。

清单 1 显示了一个非常复杂的 GRUB 配置文件。在浏览它时,请记住一件重要的事: GRUB(至少是 GRUB Legacy)会从 0 开始对驱动器、分区和需要计数的资源进行计数,而不是从 1 开始。 CentOS 的第二项有一个非常长的内核行。 清单 1显示了包含反斜杠 (\) 的内核行,反斜杠指出了需要断行的地方,以便让版面变得美观。

清单 1. /boot/grub/menu.lst GRUB 配置示例
# grub.conf generated by anaconda
#
# You do not have to rerun grub after making changes to this file
# NOTICE:You do not have a /boot partition.This means that
#          all kernel and initrd paths are relative to /, eg.
#          root (hd0,5)
#          kernel /boot/vmlinuz-version ro root=/dev/hda6
#          initrd /boot/initrd-version.img
#boot=/dev/hda
default=0
timeout=60
splashimage=(hd0,0)/boot/grub/splash.xpm.gz
#password --md5 $1$y.uQRs1W$Sqs30hDB3GtE957PoiDWO.

title Fedora 22 64-bit (sda5)
	root (hd0,4)
        kernel /boot/grub2/i386-pc/core.img

title Fedora 18 64-bit (sda7)
	root (hd0,6)
        kernel /boot/grub2/i386-pc/core.img

title CentOS 6 64-bit (sda11)
        root (hd0,10)
        configfile /boot/grub/menu.lst

title CentOS (2.6.32-504.23.4.el6.x86_64)
	root (hd0,10)
	kernel /boot/vmlinuz-2.6.32-504.23.4.el6.x86_64 ro \
           root=UUID=2f60a3b4-ef6c-4d4c-9ef4-50d7f75124a2 rd_NO_LUKS rd_NO_LVM \
           LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=128M \
           KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
	initrd /boot/initramfs-2.6.32-504.23.4.el6.x86_64.img

title Fedora 20 64-bit (sda10)
	root (hd0,9)
        configfile /boot/grub/menu.lst

title Ubuntu 12.04-LTS 64-bit (sda9)
	root (hd0,8)
        kernel /boot/grub/core.img

title Ubuntu 14.04 32-bit (sda12)
	root (hd0,11)
        kernel /boot/grub/core.img

title Slackware 13.37 64-bit (sda6)
	root (hd0,5)
        chainloader +1
        boot
	
title Open SUSE 11.4 64-bit (sda8)
	root (hd0,7)
        configfile /boot/grub/menu.lst

title Windows Example
	rootnoverify (hd0,0)
	chainloader +1
#####

清单 1 中的第一组选项控制 GRUB 如何操作。对于 GRUB,这些选项被称为菜单命令,它们必须显示在其他命令之前。其余部分为您想要允许 GRUB 引导的操作系统提供了按映像划分的选项。“Title” 被认为是一个菜单命令。每个 title 实例后面都有一个或多个一般命令或菜单项命令。

适用于 清单 1 中的其他所有部分的菜单命令是:

#
任何以 # 开头的行都是注释,GRUB 会忽略它们。这个特定的配置文件最初是由 anaconda(Red Hat 安装程序)生成的。如果在安装 Linux 时安装了 GRUB,那么您可能会发现 GRUB 配置文件中添加了一些注释。 这些注释通常用于帮助系统升级程序,以便您的 GRUB 配置能够与升级后的内核保持一致。如果自行编辑该配置,请注意为此用途而保留的所有标记。
default
如果用户没有在超时时间内做出选择,该命令会指定要加载哪个系统。在 清单 1 中,default=0 表示加载第一个条目。 请记住,GRUB 从 0 而不是从 1 开始计数。如果未指定,那么默认值是引导第一个条目,也就是编号为 0 的条目。
timeout
指定引导默认条目之前的超时时间,以秒为单位。请注意,LILO 使用 0.1 秒为超时单位,而 GRUB 使用 1 秒作为超时单位。
splashimage
指定将和引导菜单一起显示的背景(或初始)图像。GRUB Legacy 将第一个硬盘驱动器称为 (hd0),将该驱动器的第一个分区称为 (hd0,0),所以指定 splashimage=(hd0,0)/boot/grub/splash.xpm.gz 表示使用位于第一个硬盘驱动器上的分区 1 上的文件 /boot/grub/splash.xpm.gz。请记住,从 0 开始计数。该图像是一个使用 gzip 压缩的 XPM 文件。对 splashimage 的支持需要一个补丁,该补丁可能未包含在您的发行版中。
password
指定在您能够解锁菜单、编辑一个配置行或输入 GRUB 命令之前必须输入的密码。这个密码可能是明文形式的。GRUB 还允许将密码存储为 MD5 摘要,就像 清单 1 中注释掉的示例一样。这种形式更加安全,而且大多数管理员都会设置密码。无需设置密码,用户就能完全访问 GRUB 命令行。

清单 1 显示了 /dev/sda11 (hd0,10) 上的一个 CentOS 内核 /boot/vmlinuz-2.6.32-504.23.4.el6.x86_64,以及一些配置为链式加载的系统。清单 1还包含通过 /boot/grub2/i386-pc/core.img 加载 GRUB 2 的示例,以及一个典型的 Windows XP 链式加载条目的示例,但此系统实际上没有安装 Windows。这些部分中使用的命令是:

title
这是一个描述性标题,在执行 Grub 引导时显示为菜单项。 使用箭头键上下移动标题列表,然后按下 Enter 选择一个特殊条目。
root
指定将要引导的分区。和 splashimage 一样,请记住是从 0 开始计数的,因此指定为 root (hd0,6) 的第一个 Red Hat 系统实际上位于第一个硬盘驱动器的第 7 个分区上(在本例中为 /dev/hda7),而指定为 root (hd1,10) 的第一个 Ubuntu 系统位于第二个硬盘驱动器上 (/dev/hdb11)。GRUB 尝试挂载此分区来检查它,并在某些情况下向已引导的操作系统提供一些值。
kernel
指定要加载的内核映像和所需的所有内核参数。kernel 值(比如 /boot/grub2/i386-pc/core.img)通常表示从指定的根分区加载一个 GRUB 2 引导加载程序。
initrd
这是初始 RAM 磁盘的名称,该磁盘包含内核在挂载文件系统前需要的模块。
savedefault
本示例中未使用。如果指定了菜单命令 default=saved 并对某个操作系统指定了 savedefault 命令,那么引导该操作系统会导致它成为默认选择,直到引导了另一个指定了 savedefault 的操作系统。在 清单 1 中,指定 default=0 会覆盖所有已保存的默认值。
boot
这是一个可选的参数,告诉 GRUB 引导所选的操作系统。这是处理完某次选择的所有命令后的默认操作。
lock
未包含在 清单 1 中。在输入密码之前,不会引导指定的条目。如果使用此命令,那么您还应该在初始选项中指定一个密码;否则,用户可以编辑您的锁定选项并引导系统,或者向其他条目之一添加 “single”。如果您愿意的话,还可以为个别条目指定不同的密码。
rootnoverify
类似于 root,但 GRUB 不会尝试挂载文件系统或验证其参数。这通常用于不受 GRUB 支持的文件系统,比如 NTFS。如果想要 GRUB 加载一个硬盘驱动器上的主引导记录(例如,用于访问不同的配置文件或重新加载您以前的引导加载程序),也可以使用此命令。
chainloader
指定另一个将加载为阶段 1 文件的文件。值 “+1” 等效于 0+1,表示加载一个从扇区 0 开始的扇区;也就是说,加载 root 或 rootnoverify 所指定的设备的第一个扇区。
configfile
指定正在运行的 GRUB 副本使用从目标位置加载的配置文件替换其配置文件。为了实现此目的,最好让加载新配置文件的 GRUB 版本与构建它的版本同样新。

现在,您已经对可在典型的 /boot/grub/grub.conf(或 /boot/grub/menu.lst)文件中找到的内容有所了解。还有其他许多 GRUB 命令对引导过程提供了广泛控制,并帮助安装 GRUB 和执行其他任务。可以在 GRUB 手册中了解有关这些的更多信息,该手册应该可以通过命令 info grub 在您系统上找到。

在学习如何处理这种大型 GRUB 配置文件之前,我们回过头来看一个更小、更简单的示例。我使用了在 /dev/sda11 上安装 CentOS 6 时它为我构建的文件。该文件如 清单 2 所示。同样地,我使用了反斜杠 (\) 来显示需要对较长的内核行进行断行的地方,以便让版面变得美观。

清单 2. CentOS 6 构建的基本 GRUB 配置
# grub.conf generated by anaconda
#
# You do not have to rerun grub after making changes to this file
# NOTICE:You do not have a /boot partition.This means that
#          all kernel and initrd paths are relative to /, eg.
#          root (hd0,10)
#          kernel /boot/vmlinuz-version ro root=/dev/sdd11
#          initrd /boot/initrd-[generic-]version.img
#boot=/dev/sdd11
default=0
timeout=5
splashimage=(hd0,10)/boot/grub/splash.xpm.gz
hiddenmenu
title CentOS (2.6.32-504.23.4.el6.x86_64)
	root (hd0,10)
	kernel /boot/vmlinuz-2.6.32-504.23.4.el6.x86_64 ro \
           root=UUID=2f60a3b4-ef6c-4d4c-9ef4-50d7f75124a2 rd_NO_LUKS rd_NO_LVM \
           LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=128M \
           KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
	initrd /boot/initramfs-2.6.32-504.23.4.el6.x86_64.img
title CentOS 6 (2.6.32-504.el6.x86_64)
	root (hd0,10)
	kernel /boot/vmlinuz-2.6.32-504.el6.x86_64 ro \
           root=UUID=2f60a3b4-ef6c-4d4c-9ef4-50d7f75124a2 rd_NO_LUKS rd_NO_LVM \
           LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=128M \
           KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
	initrd /boot/initramfs-2.6.32-504.el6.x86_64.img
title Other
	rootnoverify (hd0,0)
	chainloader +1

请注意之前未曾看到过的命令 hiddenmenu。 这会导致 GRUB 不显示菜单,而是在超时结束后立即引导默认条目。在我们的例子中,这意味着将在 5 秒内 (timeout=5) 引导第一个条目 (default=0)。如果在此期间按下 Enter,则会显示菜单。

在拥有 GRUB 配置文件后,需要安装它,或者最好是测试它。我首先将介绍如何进行安装,然后展示如何使用软盘(如果您还有)或 CD 测试它。

我会将 GRUB 安装在包含我的 CentOS 发行版的分区的分区引导记录中。我使用了grub-install 命令,并指定了 512 字节的阶段 1 引导加载程序应该访问的设备。在我的示例中,该设备是 /dev/sda11 或使用 GRUB 记法 (notation) 的 (hd0,10)。参见 清单 3。您需要拥有根权限,然后才能编写分区引导记录。如果添加或删除了设备,您可能 需要删除 /boot/grub/device.map 文件,并允许 grub-install 重新构建它,如我们的示例中所示。这种情况不会经常发生,但是,如果 grub-install 抛出某个您无法理解的奇怪错误,您可能发现删除 device.map 文件会对您有所帮助。

清单 3. 将 GRUB Legacy 安装在分区引导记录中
[root@attic4-cent ~]# rm /boot/grub/device.map 
rm: remove regular file `/boot/grub/device.map'?y
[root@attic4-cent ~]# grub-install /dev/sda11
Probing devices to guess BIOS drives.This might take a long time.
Installation finished.No error reported.
This is the contents of the device map /boot/grub/device.map.
Check if this is correct or not.If any of the lines is incorrect,
fix it and re-run the script `grub-install'.

(fd0)	/dev/fd0
(hd0)	/dev/sda
(hd1)	/dev/sdb
(hd2)	/dev/sdc
(hd3)	/dev/sdd

由于您已经知道标准 DOS MBR 无法引导逻辑分区,所以需要采用其他某个工具来引导此系统。一种选择是通过运行 grub-install /dev/sda 将 GRUB 安装在 MBR 中,这还会将 GRUB 安装在我们磁盘 (/dev/sda) 的 MBR 中。稍后我还会向您展示如何使用 GRUB 2 实现此目的,但在决定采用方法步骤之前,您可能想要使用 GRUB 引导 CD 测试您的设置。

构建可引导的 GRUB 急救 CD

在重新引导您的新系统之前,构建一个可引导的 GRUB CD 可能是一个好主意。首先,在硬盘驱动器上准备一个 CD 映像。您需要一个临时目录,假设该目录名为 grubcd,其中包含子目录 boot 和 boot/grub。随后需要将 stage2_eltorito 文件从您的 GRUB 发行版文件复制到您刚创建的 grub 目录。然后,使用 genisoimage 创建一个可引导的 .iso 映像文件,您可以使用您最喜欢的刻录工具将它刻录到 CD 上。清单 4展示了如何将 CD 映像创建为 grubcd.iso。执行此操作不需要根权限。我们的 stage2_eltorito 位于 /usr/share/grub/x86_64-redhat 中。此位置在其他系统上可能有所不同,特别是 32 位系统。或者,您可能会在 /usr/lib/grub 下找到它。可以使用 locate 命令来查找它,如 清单 4 中所示。

清单 4. 创建一个 GRUB 可引导 CD 映像
[ian@attic4-cent ~]$ mkdir mkdir -p grubcd/boot/grub
[ian@attic4-cent ~]$ ls /usr/share/grub/
x86_64-redhat
[ian@attic4-cent ~]$ ls /usr/share/grub/x86_64-redhat/stage2_eltorito
/usr/share/grub/x86_64-redhat/stage2_eltorito
[ian@attic4-cent ~]$ locate stage2_eltorito
/usr/share/grub/x86_64-redhat/stage2_eltorito
[ian@attic4-cent ~]$ cp /usr/share/grub/x86_64-redhat/stage2_eltorito grubcd/boot/grub
[ian@attic4-cent ~]$ genisoimage -R -b boot/grub/stage2_eltorito -no-emul-boot \
> -boot-load-size 4 -boot-info-table -o grubcd.iso grubcd
I:-input-charset not specified, using utf-8 (detected in locale settings)
Size of boot image is 4 sectors -> No emulation
Total translation table size:2048
Total rockridge attributes bytes:760
Total directory bytes:4576
Path table size(bytes):34
Max brk space used 22000
241 extents written (0 MB)

您可以在任意 PC 中引导此 CD;该 PC 不需要是安装了 Linux 系统的 PC。如果引导该 CD,则会从 CD 加载 GRUB shell。在引导时,会获得一个 GRUB 引导提示符。可以按下 tab 键或使用 help 命令来查看可用命令的列表。还可以尝试使用 help commandname 获得关于名为 commandname 的命令的帮助。

在使用 CD 重新引导之前,还有最后一件事要做:您可以从 Linux 命令行练习 GRUB shell 中可用的一些 GRUB 命令。清单 5 演示了 grub 命令和一些可用的命令,包括显示菜单和查看它是否是您想要的。一些命令(比如 find)需要 root 权限,所以我的示例使用了 root 用户。还要注意的是,在尝试按下 Enter 来加载第一个配置条目时,GRUB 会因为分段错误而崩溃。请记住,您可以从 Bash 命令行练习部分 GRUB shell 命令,而不是所有命令。向上和向下箭头键可能不可用。同样地,较长的内核行已使用 \ 进行拆分。

清单 5. GRUB 命令行
[root@attic4-cent ~]# grub
Probing devices to guess BIOS drives.This might take a long time.


    GNU GRUB  version 0.97  (640K lower / 3072K upper memory)

 [ Minimal BASH-like line editing is supported.For the first word, TAB
   lists possible command completions.Anywhere else TAB lists the possible
   completions of a device/filename.]
grub> help rootnoverify
help rootnoverify
rootnoverify: rootnoverify [DEVICE [HDBIAS]]
    Similar to `root', but don't attempt to mount the partition.This 
    is useful for when an OS is outside of the area of the disk that 
    GRUB can read, but setting the correct root device is still 
    desired.The items mentioned in `root' which derived 
    from attempting the mount will NOT work correctly.
grub> find /boot/grub/menu.lst
find /boot/grub/menu.lst
 (hd0,0)
 (hd0,7)
 (hd0,10)
grub> configfile (hd0,10)/boot/grub/menu.lst
configfile (hd0,10)/boot/grub/menu.lst

Press any key to enter the menu


    GNU GRUB  version 0.97  (640K lower / 3072K upper memory)

-------------------------------------------------------------------
 0:CentOS (2.6.32-504.23.4.el6.x86_64)
 1:CentOS 6 (2.6.32-504.el6.x86_64)
 2:Other
-------------------------------------------------------------------

      Use the ^ and v keys to select which entry is highlighted.
      Press enter to boot the selected OS, 'e' to edit the
      commands before booting, 'a' to modify the kernel arguments
      before booting, or 'c' for a command-line.

The selected entry is 0     Highlighted entry is 0: 

  Booting 'CentOS (2.6.32-504.23.4.el6.x86_64)'

root (hd0,10)
 Filesystem type is ext2fs, partition type 0x83
kernel /boot/vmlinuz-2.6.32-504.23.4.el6.x86_64 ro \
root=UUID=2f60a3b4-ef6c-4d4c-9ef4-50d7f75124a2 rd_NO_LUKS rd_NO_LVM \
LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=128M  \
KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
   [Linux-bzImage, setup=0x3400, size=0x3f2790]
Segmentation fault (core dumped)

在此示例中,第一个硬盘驱动器上的三个不同分区上有 GRUB 配置文件,包括 (hd0,10) 或 /dev/sda11 上为 CentOS 构建的一个配置文件。清单 5使用 configfile 命令从 (hd0,10) 加载 GRUB 菜单。

还可以在 GRUB 手册中了解这些 GRUB 命令。尝试在 Linux 终端窗口中键入 info grub 来打开该手册。

如果您有软盘,可以使用
grub-install /dev/fd0
等命令将 GRUB 安装在软盘上,其中 /dev/fd0 对应于您的软盘驱动器。在将 GRUB 安装在软盘上之前,您应该卸载该软盘。

使用 GRUB Legacy 进行引导

现在,您已经准备好使用刚构建的 GRUB CD 来重新引导您的系统了。如果 BIOS 未被设置为自动从 CD 或 DVD(如果已存在)进行引导,那么您可能需要按下某个特定于系统的键(在我的 BIOS 上为 F8)来选择硬盘驱动器以外的一个引导设备。从 CD 引导至一个 GRUB 提示符,如 图 1 所示。

图 1. 引导您的 GRUB CD
Booting your GRUB CD
Booting your GRUB CD

在这个示例中,我使用了 find 命令来查找名为 menu.lst 的 GRUB 配置文件,找到 3 个文件,包括设备 (hd0,10) 或 /dev/sda11 上的 CentOS GRUB 配置文件。然后,我使用了 root 命令来将 (hd0,10) 设置为根,以便执行进一步的文件操作。我将 GRUB 安装在 (hd0,10) 的分区引导记录中,所以我使用chainloader 命令来告诉 GRUB 引导 (hd0,10) 的第一个扇区中的任何引导加载程序。最后,我使用 boot 命令来引导这个新的加载程序(在我们的示例中同样是 GRUB)。结果请参见 图 2

图 2. CentOS Grub 菜单
The CentOS Grub menu
The CentOS Grub menu

在这种情况下,可按下 Enter 来查看该菜单。否则 hiddenmenu 选项只会显示正在引导的行和一个倒数计时器。

在 GRUB shell 中执行编辑

现在,我将介绍如何使用 GRUB shell 编辑配置。出于此目的,您将引导进入单用户模式,但在必要时,您可以更改任何行,甚至添加或删除所有配置行。 例如,如果您忘记了 root 行,那么可以添加它。可以按下 e 来编辑配置,然后使用向下箭头来突出显示 kernel 行。结果如 图 3 所示。

图 3. 编辑 kernel 行
Editing the kernel line to boot in single user mode
Editing the kernel line to boot in single user mode

再次按下 e,然后在该行的末尾处键入单词 single,如 图 4 所示。

图 4. 编辑 kernel 行
Editing the kernel line to boot in single user mode
Editing the kernel line to boot in single user mode

最后,按下 Enter 返回到您在 图 2 中看到的屏幕,然后按下 b 将 CentOS 引导进入单用户模式。在执行系统引导时,会有一个根提示符。可以使用此模式对无法正常引导的系统进行紧急修复。

此刻,您可以重复以前的过程来引导进入正常的图形模式或者您设置您的系统引导进入的任何模式。如果想让 GRUB 控制系统上的所有引导,那么现在可以运行
grub-install /dev/sda
将 GRUB 安装在 /dev/sda 的 MBR 中。随着继续学习本教程,您会看到其他管理引导的方式。

GRUB 2

GRUB 2 是 GRUB 的继任者。它是完全重新编写的,以便使其更加模块化和可移植。它面向许多不同的架构和引导方法,拥有许多新特性,包括处理 UEFI 固件和 GPT 格式的驱动器的能力。请参见参考资料,获取更多信息的链接。如果熟悉 GRUB 并开始使用 GRUB 2,您会发现它们完全不同,而且您可能会获得很多惊喜。

备注:本教程中的大部分 GRUB 2 示例都使用了 Fedora 22 或 Ubuntu 15。

对于 GRUB 2,您可能注意到的第一点是,它不能作为一个分区引导加载程序进行安装。如果告诉 Linux 安装程序将 GRUB 安装在一个分区中,该分区将无法通过链式加载进行引导。 在更新系统后,必须重新构建 GRUB 2。大多数系统更新流程都会为您完成此操作,但是,如果一个系统上有多个操作系统,您可能需要自行完成一些工作。 现在,我将介绍如何单独使用 GRUB 2,或者将它与 GRUB Legacy 结合使用。

GRUB 2 包里有几个程序通常位于 /usr/bin 或 /usr/sbin 中。实际的包名称在不断改变,对于所有发行版可能有所不同。这些二进制文件的名称通常也是以 grub- 或 grub2- 开头。例如,在 Ubuntu 14 上,您会找到包 grub-common 提供的 grub-image;而在 Fedora 22 上,您会找到包 grub2-tools 提供的 grub2-mkimage。请参阅学习 Linux,101:Debian 包管理学习 Linux,101:RPM 和 YUM 包管理,获得关于查找包含一个特殊命令的包的帮助。清单 6显示了一个 Ubuntu 14.04 系统上的 GRUB 二进制文件。和平常一样,请查阅手册页或尝试使用 --help 选项运行程序,以获得更多的信息。您可能需要在网络上进行搜索来获得更多的帮助。由于技术的迅猛发展,所以请做好会在文档中发现不一致性的心理准备。

清单 6. /usr/bin 和 /usr/sbin 中的 GRUB 2 可执行文件
ian@attic-u14:~$ which grub-image
/usr/bin/grub-image
ian@attic-u14:~$ dpkg -S /usr/bin/grub-image
grub-common:/usr/bin/grub-image
ian@attic-u14:~$ dpkg -L grub-common | grep "bin/"
/usr/sbin/grub-mkdevicemap
/usr/sbin/grub-mkconfig
/usr/sbin/grub-probe
/usr/sbin/grub-macbless
/usr/bin/grub-glue-efi
/usr/bin/grub-mkfont
/usr/bin/grub-script-check
/usr/bin/grub-fstest
/usr/bin/grub-mkstandalone
/usr/bin/grub-image
/usr/bin/grub-mklayout
/usr/bin/grub-mkrescue
/usr/bin/grub-mkrelpath
/usr/bin/grub-kbdcomp
/usr/bin/grub-render-label
/usr/bin/grub-mount
/usr/bin/grub-file
/usr/bin/grub-menulst2cfg
/usr/bin/grub-editenv
/usr/bin/grub-syslinux2cfg
/usr/bin/grub-mkpasswd-pbkdf2
/usr/bin/grub-mknetdir

GRUB 2 的核心是一个多引导内核 (/boot/grub/core.img) 和一个配置文件 (/boot/grub/grub.cfg)。如果运行 grub-install 并将目标设置为您的 MBR(例如:grub-install /dev/sda),就会为您生成这些。可以运行 grub-install --help(如 清单 7 中所示)来了解被调用来执行所有这些工作的程序。一些程序与 Grub Legacy 类似,但也有一些新程序,比如 --modules--grub-setup--grub-image 等。

清单 7. 针对 grub-install 的 GRUB 2 帮助
ian@attic-u14:~$ grub-install --help
Usage: grub-install [OPTION...][OPTION] [INSTALL_DEVICE]
Install GRUB on your drive.

      --compress[=no,xz,gz,lzo]   compress GRUB files [optional]
  -d, --directory=DIR        use images and modules under DIR
                             [default=/usr/lib/grub/<platform>]
      --fonts=FONTS          install FONTS [default=unicode]
      --install-modules=MODULES   install only MODULES and their dependencies
                             [default=all]
  -k, --pubkey=FILE          embed FILE as public key for signature checking
      --locale-directory=DIR use translations under DIR
                             [default=/usr/share/locale]
      --locales=LOCALES      install only LOCALES [default=all]
      --modules=MODULES      pre-load specified modules MODULES
      --themes=THEMES        install THEMES [default=starfield]
  -v, --verbose              print verbose messages.
      --allow-floppy         make the drive also bootable as floppy (default
                             for fdX devices).May break on some BIOSes.
      --boot-directory=DIR   install GRUB images under the directory DIR/grub
                             instead of the boot/grub directory
      --bootloader-id=ID     the ID of bootloader.This option is only
                             available on EFI and Macs.
      --core-compress=xz|none|auto
                             choose the compression to use for core image
      --disk-module=MODULE   disk module to use (biosdisk or native).This
                             option is only available on BIOS target.
      --efi-directory=DIR    use DIR as the EFI System Partition root.
      --force                install even if problems are detected
      --force-file-id        use identifier file even if UUID is available
      --label-bgcolor=COLOR  use COLOR for label background
      --label-color=COLOR    use COLOR for label
      --label-font=FILE      use FILE as font for label
      --macppc-directory=DIR use DIR for PPC MAC install.
      --no-bootsector        do not install bootsector
      --no-nvram             don't update the `boot-device'/`Boot*' NVRAM
                             variables.This option is only available on EFI
                             and IEEE1275 targets.
      --no-rs-codes          Do not apply any reed-solomon codes when
                             embedding core.img.This option is only available
                             on x86 BIOS targets.
      --no-uefi-secure-boot  do not install an image usable with UEFI Secure
                             Boot, even if the system was currently started
                             using it.This option is only available on EFI.
      --product-version=STRING   use STRING as product version
      --recheck              delete device map if it already exists
      --removable            the installation device is removable.This option
                             is only available on EFI.
  -s, --skip-fs-probe        do not probe for filesystems in DEVICE
      --target=TARGET        install GRUB for TARGET platform
                             [default=i386-pc]
      --uefi-secure-boot     install an image usable with UEFI Secure Boot.
                             This option is only available on EFI and if the
                             grub-efi-amd64-signed package is installed.
  -?, --help                 give this help list
      --usage                give a short usage message
  -V, --version              print program version

Mandatory or optional arguments to long options are also mandatory or optional
for any corresponding short options.

INSTALL_DEVICE must be system device filename.
grub-install copies GRUB images into boot/grub.On some platforms, it may
also install GRUB into the boot sector.

Report bugs to <bug-grub@gnu.org>.

如果运行 grub-install /dev/sda,该过程会为您构建一个核心映像文件,构建一个配置文件,并将 GRUB 2 安装在您的 MBR 中。如果还没有准备好在您的全部设置中使用 GRUB 2,您可以自行构建这些部分,然后从 GRUB Legacy 或 LILO 引导 GRUB 2 核心映像。

构建 GRUB 2 配置文件

GRUB 2 配置文件通常是 /boot/grub/grub.cfg。不同于 GRUB Legacy,您通常不应自行编辑此文件,因为下次更新您的 GRUB 2 安装时会覆盖它。您应该使用 grub-mkconfig 构建它。在一些系统上,比如 Ubuntu,update-grub 命令是 grub-mkconfig 的前端,后者将其输出保存在 /boot/grub/grub.cfg 中。 这些命令在 /etc/default/grub 中寻找一般设置(比如背景或超时),然后运行 /etc/grub.d/ 中的可执行文件来构建配置文件的各个部分,比如标头、针对当前 Linux 发行版的部分、针对其他操作系统的部分,以及您自己的自定义增加项。如果需要自定义 GRUB 2 菜单,那么您应该将更改添加到 /etc/grub.d/ 中的一个文件中,比如 40_custom,或者添加您自己的文件。请记住,该文件必须是可执行文件。 稍后在介绍如何从 GRUB 2 链式加载 GRUB Legacy 时,会展示一个自定义示例。

运行 grub-mkconfig(或者 update-grub,如果该命令可用)来生成一个新的 /boot/grub/grub.cfg 文件,如 清单 8 所示。

清单 8. 使用 grub-mkconfig 构建一个 GRUB 2 配置文件
ian@attic-u14:~$ sudo grub-mkconfig -o /boot/grub/grub.cfg
Generating grub configuration file ...
Found linux image:/boot/vmlinuz-3.16.0-43-generic
Found initrd image:/boot/initrd.img-3.16.0-43-generic
Found linux image:/boot/vmlinuz-3.16.0-30-generic
Found initrd image:/boot/initrd.img-3.16.0-30-generic
Found memtest86+ image:/boot/memtest86+.elf
Found memtest86+ image:/boot/memtest86+.bin
Found Fedora release 20 (Heisenbug) on /dev/sda10
Found CentOS release 6.6 (Final) on /dev/sda11
Found Fedora release 22 (Twenty Two) on /dev/sda5
Found Slackware Linux (Slackware 13.37.0) on /dev/sda6
Found Fedora release 18 (Spherical Cow) on /dev/sda7
Found openSUSE 11.4 (x86_64) on /dev/sda8
Found Ubuntu 12.04 LTS (12.04) on /dev/sda9
done

清单 9 显示了结果配置文件的标头部分,清单 10 显示了前几个菜单项。我已经说过,为了版面美观,较长的行已使用一个反斜杠 (\) 进行断行。请注意,menuentry 代码段看起来更像是 shell 脚本,而不像是没有 GRUB Legacy 逻辑的纯命令。与 GRUB Legacy 不同的另一个重要变化是,尽管磁盘编号仍从 0 开始,但分区编号现在是从 1 开始。所以 /dev/sda7 在 GRUB 2 中为 (hd0,7),而在 GRUB Legacy 中则为 (hd0,6)。GRUB 2 也可以使用一个可选的分区名称和一个编号。所以 (hd0,7) 也可以称为 (hd0,msdos7),以明确指出它位于一个 MBR 格式的磁盘上。在 GPT 格式的磁盘上,您将使用 (hd0,gpt7)。

清单 9. GRUB 2 配置文件标头
#
# DO NOT EDIT THIS FILE
#
# It is automatically generated by grub-mkconfig using templates
# from /etc/grub.d and settings from /etc/default/grub
#

### BEGIN /etc/grub.d/00_header ###
if [ -s $prefix/grubenv ]; then
  set have_grubenv=true
  load_env
fi
if [ "${next_entry}" ] ; then
   set default="${next_entry}"
   set next_entry=
   save_env next_entry
   set boot_once=true
else
   set default="0"
fi

if [ x"${feature_menuentry_id}" = xy ]; then
  menuentry_id_option="--id"
else
  menuentry_id_option=""
fi

export menuentry_id_option

if [ "${prev_saved_entry}" ]; then
  set saved_entry="${prev_saved_entry}"
  save_env saved_entry
  set prev_saved_entry=
  save_env prev_saved_entry
  set boot_once=true
fi

function savedefault {
  if [ -z "${boot_once}" ]; then
    saved_entry="${chosen}"
    save_env saved_entry
  fi
}
function recordfail {
  set recordfail=1
  if [ -n "${have_grubenv}" ]; then if [ -z "${boot_once}" ]; then save_env recordfail; fi; fi
}
function load_video {
  if [ x$feature_all_video_module = xy ]; then
    insmod all_video
  else
    insmod efi_gop
    insmod efi_uga
    insmod ieee1275_fb
    insmod vbe
    insmod vga
    insmod video_bochs
    insmod video_cirrus
  fi
}

if [ x$feature_default_font_path = xy ] ; then
   font=unicode
else
insmod part_msdos
insmod ext2
set root='hd0,msdos12'
if [ x$feature_platform_search_hint = xy ]; then
  search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos12 --hint-efi=hd0,msdos12 \
    --hint-baremetal=ahci0,msdos12  943524cc-19a9-4237-ac9e-5c1a61a131e3
else
  search --no-floppy --fs-uuid --set=root 943524cc-19a9-4237-ac9e-5c1a61a131e3
fi
    font="/usr/share/grub/unicode.pf2"
fi

if loadfont $font ; then
  set gfxmode=auto
  load_video
  insmod gfxterm
  set locale_dir=$prefix/locale
  set lang=en_US
  insmod gettext
fi
terminal_output gfxterm
if [ "${recordfail}" = 1 ] ; then
  set timeout=30
else
  if [ x$feature_timeout_style = xy ] ; then
    set timeout_style=menu
    set timeout=60
  # Fallback normal timeout code in case the timeout_style feature is
  # unavailable.
  else
    set timeout=60
  fi
fi
### END /etc/grub.d/00_header ###
清单 10. 一些 GRUB 2 配置文件菜单项
### BEGIN /etc/grub.d/10_linux ###
function gfxmode {
	set gfxpayload="${1}"
	if [ "${1}" = "keep" ]; then
		set vt_handoff=vt.handoff=7
	else
		set vt_handoff=
	fi
}
if [ "${recordfail}" != 1 ]; then
  if [ -e ${prefix}/gfxblacklist.txt ]; then
    if hwmatch ${prefix}/gfxblacklist.txt 3; then
      if [ ${match} = 0 ]; then
        set linux_gfx_mode=keep
      else
        set linux_gfx_mode=text
      fi
    else
      set linux_gfx_mode=text
    fi
  else
    set linux_gfx_mode=keep
  fi
else
  set linux_gfx_mode=text
fi
export linux_gfx_mode
menuentry 'Ubuntu' --class ubuntu --class gnu-linux --class gnu \
    --class os $menuentry_id_option \
    'gnulinux-simple-943524cc-19a9-4237-ac9e-5c1a61a131e3' {
	recordfail
	load_video
	gfxmode $linux_gfx_mode
	insmod gzio
	insmod part_msdos
	insmod ext2
	set root='hd0,msdos12'
	if [ x$feature_platform_search_hint = xy ]; then
	  search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos12 \
       --hint-efi=hd0,msdos12 --hint-baremetal=ahci0,msdos12  ]
       943524cc-19a9-4237-ac9e-5c1a61a131e3
	else
	  search --no-floppy --fs-uuid --set=root 943524cc-19a9-4237-ac9e-5c1a61a131e3
	fi
	linux	/boot/vmlinuz-3.16.0-43-generic root=UUID=943524cc-19a9-4237-ac9e-5c1a61a131e3 \
        ro quiet splash $vt_handoff
	initrd	/boot/initrd.img-3.16.0-43-generic
}
submenu 'Advanced options for Ubuntu' $menuentry_id_option \
    'gnulinux-advanced-943524cc-19a9-4237-ac9e-5c1a61a131e3' {
	menuentry 'Ubuntu, with Linux 3.16.0-43-generic' --class ubuntu \
     --class gnu-linux --class gnu --class os $menuentry_id_option \
     'gnulinux-3.16.0-43-generic-advanced-943524cc-19a9-4237-ac9e-5c1a61a131e3' {
		recordfail
		load_video
		gfxmode $linux_gfx_mode
		insmod gzio
		insmod part_msdos
		insmod ext2
		set root='hd0,msdos12'
		if [ x$feature_platform_search_hint = xy ]; then
		  search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos12 \
          --hint-efi=hd0,msdos12 --hint-baremetal=ahci0,msdos12  \
          943524cc-19a9-4237-ac9e-5c1a61a131e3
		else
		  search --no-floppy --fs-uuid --set=root 943524cc-19a9-4237-ac9e-5c1a61a131e3
		fi
		echo	'Loading Linux 3.16.0-43-generic ...'
		linux	/boot/vmlinuz-3.16.0-43-generic \
          root=UUID=943524cc-19a9-4237-ac9e-5c1a61a131e3 ro quiet splash $vt_handoff
		echo	'Loading initial ramdisk ...'
		initrd	/boot/initrd.img-3.16.0-43-generic
	}
	menuentry 'Ubuntu, with Linux 3.16.0-43-generic (recovery mode)' --class ubuntu \
     --class gnu-linux --class gnu --class os $menuentry_id_option \
     'gnulinux-3.16.0-43-generic-recovery-943524cc-19a9-4237-ac9e-5c1a61a131e3' {
		recordfail
		load_video
		insmod gzio
		insmod part_msdos
		insmod ext2
		set root='hd0,msdos12'
		if [ x$feature_platform_search_hint = xy ]; then
		  search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos12 \
         --hinter=hd0,msdos12--bargain-basement=ahci0,msdos12  \
          943524cc-19a9-4237-ac9e-5c1a61a131e3
		else
		  search--no-floppy--fluidised--set=root 943524cc-19a9-4237-ac9e-5c1a61a131e3
		phi
		echo	'Loading Linux 3.16.0-43-generic..'
		Linux	/boot/vmlinuz-3.16.0-43-generic \
                root=UUID=943524cc-19a9-4237-ac9e-5c1a61a131e3 or \
                recovery Modesto 
		echo	'Loading initial ram disk..'
		initrd	/boot/initrd.img-3.16.0-43-generic
	}
	menu entry 'Ubuntu, with Linux 3.16.0-30-generic'--class Ubuntu \
        --class Linux--class gnu--class OS $menu entry_id_option \
         'gnulinux-3.16.0-30-generic-advanced-943524cc-19a9-4237-ac9e-5c1a61a131e3' {
		record fail
		load_video
		modem $Linux_GIF_mode
		ins mod Zion
		ins mod part_ms dos
		ins mod ext2
		set root='hd0,msdos12'
		if [ x$feature_platform_search_hint = x ]; then
		  search--no-floppy--fluidised--set=root--hint-bios=hd0,msdos12 \
         --hinter=hd0,msdos12--bargain-basement=ahci0,msdos12  \
          943524cc-19a9-4237-ac9e-5c1a61a131e3
		else
		  search--no-floppy--fluidised--set=root 943524cc-19a9-4237-ac9e-5c1a61a131e3
		phi
		echo	'Loading Linux 3.16.0-30-generic..'
		Linux	/boot/vmlinuz-3.16.0-30-generic \
                root=UUID=943524cc-19a9-4237-ac9e-5c1a61a131e3 \
                or quiet splash $VT_hand off
		echo	'Loading initial ram disk..'
		initrd	/boot/initrd.img-3.16.0-30-generic
	}
	menu entry 'Ubuntu, with Linux 3.16.0-30-generic (recovery mode)'--class Ubuntu \
         --class Linux--class gnu--class OS $menu entry_id_option \
          'gnulinux-3.16.0-30-generic-recovery-943524cc-19a9-4237-ac9e-5c1a61a131e3' {
		record fail
		load_video
		ins mod Zion
		ins mod part_ms dos
		ins mod ext2
		set root='hd0,msdos12'
		if [ x$feature_platform_search_hint = x ]; then
		  search--no-floppy--fluidised--set=root--hint-bios=hd0,msdos12 \
         --hinter=hd0,msdos12--bargain-basement=ahci0,msdos12  \
          943524cc-19a9-4237-ac9e-5c1a61a131e3
		else
		  search--no-floppy--fluidised--set=root 943524cc-19a9-4237-ac9e-5c1a61a131e3
		phi
		echo	'Loading Linux 3.16.0-30-generic..'
		Linux	/boot/vmlinuz-3.16.0-30-generic \
                root=UUID=943524cc-19a9-4237-ac9e-5c1a61a131e3 \
                or recovery Modesto 
		echo	'Loading initial ram disk..'
		initrd	/boot/initrd.img-3.16.0-30-generic
	}
}

### END /etc/grub.d/10_Linux ###

构建 GRUB 2 核心映像

构建一个新核心映像文件的最简单的方法是运行 grub-install(或根据您的系统运行 grub2-install),但不要更新 MBR。该程序的一些版本使用 -grub-setup 选项安装引导扇区,以指示实际设置了哪个程序。将此设置为 /bin/true,以便不执行任何操作并避免引导扇区更新。其他版本没有 -grub-setup 选项,但有 -non-sectarian 选项。检查手册页。我将在 清单 11 中展示两个不同的示例。我首先删除现有的 core.img,以表明确实已生成该文件。

清单 11. 使用 grub-install 或 grub2-install 构建 GRUB 2 核心映像
[root@atticf20 ~]# # Build a core.img file on Fedora 22
[root@atticf20 ~]# grub2-install --recheck --grub-setup=/bin/true /dev/sda
Installing for i386-pc platform.
Installation finished.No error reported.
[root@atticf20 ~]# ls -l /boot/grub2/i386-pc/core.img 
-rw-r--r--.1 root root 25887 Jul 12 22:56 /boot/grub2/i386-pc/core.img

ian@attic-u14:~$ # Build a core.img file on Ubuntu 14
ian@attic-u14:~$ sudo grub-install --non-sectarian /dev/sda
[sudo] password for ian: 
Installing for i386-pc platform.
Installation finished.No error reported.
ian@attic-u14:~$ ls -l /boot/grub/i386-pc/core.img 
-rw-r--r-- 1 root root 25363 Jul 12 23:15 /boot/grub/i386-pc/core.img

构建可引导的 GRUB 2 急救 CD

GRUB 2 提供了一个 grub-mkrescuegrub2-mkrescue 命令来帮助您创建一个急救 CD 映像。 grub-mkrescue 的最新版本使用 xorriso 包,而不是使用 mkisofs 包或 genisoimage 包来创建 ISO 映像,所以如果您首次尝试失败,并获得表明 Xorriso 未找到或处于错误级别的错误消息,那么您需要安装此包。清单 12 展示了如何在文件 rescue.iso 中创建一个 GRUB 2 急救映像。创建急救 ISO 不需要执行引导操作。

清单 12. 创建一个 GRUB 2 急救映像
[root@echidna ~]# /usr/bin/grub2-mkrescue -o rescue.iso
Enabling BIOS support ...
xorriso 1.2.4 :RockRidge filesystem manipulator, libburnia project.

Drive current:-outdev 'stdio:rescue.iso'
Media current: stdio file, overwriteable
Media status : is blank
Media summary:0 sessions, 0 data blocks, 0 data, 7177m free
Added to ISO image: directory '/'='/tmp/tmp.Dw4KSbpoIx'
xorriso :UPDATE :196 files added in 1 seconds
xorriso :UPDATE :196 files added in 1 seconds
xorriso :NOTE :Copying to System Area:29191 bytes from file '/tmp/tmp.LepCeiJPZM'
ISO image produced:1094 sectors
Written to medium :1094 sectors at LBA 0
Writing to 'stdio:rescue.iso' completed successfully.

在创建 ISO 映像后,可以使用您最喜欢的刻录工具将它刻录到 CD(或 DVD)中。如果您喜欢的话,还可以将它复制到一个 USB 闪存驱动器并从该驱动器进行引导,只要您的 BIOS 支持从这些设备进行引导。清单 13展示了如何使用 dd 命令将 ISO 映像复制到 USB 闪存驱动器 /dev/sde。

警告:请确保您将映像复制到了正确的设备。将它复制到错误的设备可能会毁坏大量数据。

清单 13. 将一个 GRUB 2 急救映像写入 USB 闪存驱动器
ian@attic-u14:~$ # Burn .iso image to USB stick /dev/sde
ian@attic-u14:~$ sudo dd if=rescue.iso of=/dev/sde
9864+0 records in
9864+0 records out
5050368 bytes (5.1 MB) copied, 3.95946 s, 1.3 MB/s

您现在应该有一个可引导的 CD 或可引导的 USB 闪存驱动器,它将引导进入一个 GRUB 2 提示符。

使用 GRUB 2 进行引导

您将引导 USB 闪存驱动器来查看它的工作原理。和 GRUB Legacy 一样,这个急救磁盘引导进入一个 GRUB 提示符,您可以在这里输入命令。我将展示一些命令,您可以使用它们来启动我之前为其构建了配置文件的 Ubuntu 14 系统。图 5显示了执行引导并输入一些命令后的屏幕。

图 5. 引导 GRUB 2 急救闪存驱动器

输入的命令为:

ls
没有参数,列出找到的设备。此命令的运行可能会花费一些时间。闪存驱动器通常不是 BIOS 驱动器,但是,如果从一个闪存驱动器引导,它可能会显示为 hd0 并取代其他驱动器,导致它们没有按您预期的进行编号。可以使用可引导的 CD 或 DVD 来避免这个问题。
set
设置变量值。在本例中,您可以设置 root 变量。与 GRUB Legacy root 命令进行比较。您使用 hd1 代替了 hd0,因为前面的命令已告诉您,hd0 现在是您从中引导的 USB 闪存驱动器。
ls
有一个路径,显示了文件或目录。使用类似 Bash 的 tab 键补全功能来补全您键入的路径组件,或者获取可能的补全列表,就像在这里看到的一样(我在输入 /boot/grub/gru 后按下 tab 键)。
configfile
和 GRUB Legacy 一样,可以使用 configfile 命令加载配置文件。我们加载了之前构建的一个配置文件。

在加载配置文件后,您的屏幕类似于 图 6

图 6. 针对 GRUB2 的 Ubuntu 14 配置文件

和 GRUB Legacy 一样,您可以在引导系统之前编辑配置条目或输入命令。

可以在 GRUB 手册中进一步了解许多 GRUB 2 命令。尝试在 Linux 终端窗口中键入 info grubinfo grub2 来打开该手册。

从 GRUB Legacy 引导 GRUB 2,反之亦然

我提到过您不能从分区引导记录来链式加载 GRUB 2。 在构建核心映像和配置文件后,向 GRUB Legacy grub.conf 或 menu.lst 文件添加一个条目来引导 GRUB 2 核心映像,然后,后者会显示您构建的 GRUB 2 菜单。清单 14显示了我在 清单 1 中也使用了 /dev/sda12 上的 Ubuntu 14 安装。因为此配置文件适用于 GRUB Legacy,所以根条目指定 (hd0,11) 来表示 /dev/sda12。

清单 14. 用来引导 GRUB 2 核心映像的 GRUB Legacy 配置条目
title Ubuntu 14.04 32-bit (sda12)
	root (hd0,11)
        kernel /boot/grub/core.img

类似地,您可以向 GRUB 2 配置文件添加一个条目,以便链式加载 GRUB Legacy 引导加载程序。更新模板文件 /etc/grub.d/40_custom,而不是直接编辑配置文件。 清单 15显示了一个完成此任务的典型条目。这个条目来自我的 Fedora 22 安装。它将根设置为 (hd0,1),在我的系统上,这是一个特殊的引导分区,我稍后会讨论它。

清单 15. 使用 /etc/grub.d/40_custom 从 GRUB 2 链式加载 GRUB
#!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries.Simply type the
# menu entries you want to add after this comment.Be careful not to change
# the 'exec tail' line above.
menuentry "GRUB-Legacy /dev/sda1" {
	insmod chain
	insmod ext2
	set root=(hd0,1)
	chainloader +1
}

再次运行 grub-mkconfig 后,此条目会添加到配置文件末尾处,显示在最后面。

您会在本教程后面的 使用引导分区 部分看到这些方法的实际应用。

LILO

多年来,LInux LOader (LILO) 一直是最常见的 Linux 引导加载程序之一。可以将 LILO 安装到可引导的硬盘驱动器的 MBR 中,或者安装在某个分区的分区引导记录中。还可以将它安装在可移动设备上,比如软盘、CD 或 U 盘。和 GRUB 和 GRUB 2 一样,如果您还不熟悉 LILO,那么在软盘或 U 盘上练习是一个好主意。

在 Linux 安装期间,通常会指定一个引导管理器。如果选择 GRUB,那么您可能没有安装 LILO。如果还没有安装它,那么您需要安装它的包。您可能还想要安装 lilo-doc 包,以便获取额外的文档和更多的示例。从现在开始,我假设您已经安装了 LILO 包。如果需要帮助,请参阅教程的系列路线图来了解包管理。

可以使用一个配置文件来配置 LILO,这个配置文件通常是 /etc/lilo.conf。可以使用 liloconfig 命令(通常可以在 /usr/sbin 中找到)来生成一个启动配置文件,然后根据需要编辑它。清单 16 中的配置文件就是以这种方式生成的。该文件添加了明确的注释,lilo 和 lilo.conf 的手册页提供了更多的帮助。这是一个可用在包含 Windows 以及一个或多个 Linux 系统的双引导系统上的典型 LILO 配置文件。和以前一样,为了版面美观,我对一些较长的行进行了断行。断行的地方显示了一个反斜杠 (\)。

清单 16. /etc/lilo.conf 示例
# LILO configuration file
# generated by 'liloconfig'
#
# Start LILO global section
lba32 # Allow booting past 1024th cylinder with a recent BIOS
boot = /dev/root
#compact # faster, but won't work on all systems.
# Boot BMP Image.
# Bitmap in BMP format:640x480x8
bitmap = /boot/slack.bmp
# Menu colors (foreground, background, shadow, highlighted
# foreground, highlighted background, highlighted shadow):
bmp-colors = 255,0,255,0,255,0
# Location of the option table: location x, location y, number of
# columns, lines per column (max 15), "spill" (this is how many
# entries must be in the first column before the next begins to
# be used.We don't specify it here, as there's just one column.
bmp-table = 60,6,1,16
# Timer location x, timer location y, foreground color,
# background color, shadow color.
bmp-timer = 65,27,0,255
# Standard menu.
# Or, you can comment out the bitmap menu above and
# use a boot message with the standard menu:
#message = /boot/boot_message.txt

# Append any additional kernel parameters:
append=" vt.default_utf8=0"
prompt
timeout = 300
# VESA framebuffer console @ 640x480x64k
vga = 785
# Normal VGA console
#vga = normal
# Ask for video mode at boot (time out to normal in 30s)
#vga = ask
# VESA framebuffer console @ 1024x768x64k
# vga=791
# VESA framebuffer console @ 1024x768x32k
# vga=790
# VESA framebuffer console @ 1024x768x256
# vga=773
# VESA framebuffer console @ 800x600x64k
# vga=788
# VESA framebuffer console @ 800x600x32k
# vga=787
# VESA framebuffer console @ 800x600x256
# vga=771
# VESA framebuffer console @ 640x480x64k
# vga=785
# VESA framebuffer console @ 640x480x32k
# vga=784
# VESA framebuffer console @ 640x480x256
# vga=769
# ramdisk = 0 # paranoia setting
# End LILO global section
# Linux bootable partition config begins
image = /boot/vmlinuz
root = /dev/sda6
label = Slackware
read-only # Partitions should be mounted read-only for checking
# Linux bootable partition config ends

# Linux bootable partition config begins
image = /mnt/sda11/boot/vmlinuz-2.6.32-504.23.4.el6.x86_64 
	root="UUID=2f60a3b4-ef6c-4d4c-9ef4-50d7f75124a2"
append = "ro rd_NO_LUKS rd_NO_LVM LANG=en_US.UTF-8 rd_NO_MD \
    SYSFONT=latarcyrheb-sun16 crashkernel=128M  KEYBOARDTYPE=pc \
    KEYTABLE=us rd_NO_DM rhgb quiet"
	initrd = /mnt/sda11/boot/initramfs-2.6.32-504.23.4.el6.x86_64.img
	label = CentOS-vm
# Linux bootable partition config ends

# Windows bootable partition config begins
other = /dev/sda11
label = CentOS-6

# Windows bootable partition config ends

# Windows bootable partition config begins
other = /dev/sda1
label = GRUB-Legacy

# Windows bootable partition config ends

lilo 命令使用了您准备好的配置文件来设置 LILO。使用 -b 选项指定 LILO 引导扇区的位置。例如,使用 /dev/sda 表示您的第一个硬盘驱动器的 MBR,或者使用 /dev/sda6 表示第 6 个分区。

LILO 支持许多您在 GRUB 和 GRUB 2 中看到的引导时序功能 (boot time capabilities)。图 7 显示了来自 清单 16 中的配置文件的引导屏幕。

图 7. 使用 LILO 进行引导
Booting with LILO
Booting with LILO

您现在已经了解了 LILO 及其配置文件。可以从 lilo 命令行覆盖一些配置选项。可以使用命令 man liloman lilo.conf 在 lilo 手册页中找到更多的信息。您甚至可以在随 lilo 或 lilo-doc 包一起安装的 PostScript 用户指南中找到更多的信息。该指南应该安装在您的文档目录中,但准确的位置可能因系统不同而有所不同。

请记住,在使用 LILO 时,只要更新了配置文件 (/etc/lilo.conf),就必须运行 lilo 命令。如果添加、移动或删除了分区,或者执行其他任何可能使生成的引导加载程序失效的更改,也应该运行 lilo 命令。

系统更新

大多数发行版都提供了更新系统的工具。这些工具通常知道所使用的引导加载程序,常常自动更新您的配置文件。如果构建您自己的自定义内核,或者喜欢使用具有非标准名称或位置的配置文件,那么您可能需要自行更新该配置文件。

  • 如果使用 GRUB,可以编辑 /boot/grub/grub.conf 文件来执行更改,而且 GRUB 阶段 2 加载程序会在重新引导时读取该文件。通常不需要重新安装 GRUB,因为会添加一个新内核。但是,如果移动一个分区或添加驱动器,可能需要重新安装 GRUB。请记住,阶段 1 加载程序非常小,所以它拥有阶段 2 加载程序的块地址列表。 移动该分区并且地址发生了更改,这样阶段 1 加载程序就无法再找到阶段 2 加载程序。接下来我将介绍一些恢复策略,还将讨论 GRUB 的阶段 1.5 加载程序。
  • 如果使用 GRUB 2,需要按照构建 GRUB 2 配置文件中的描述重新构建 GRUB 2 配置。
  • 如果使用 LILO,只要更新了配置文件或执行了一些更改,比如添加硬盘驱动器或删除分区,就必须运行 lilo 命令。
  • 如果在不同的分区上运行多个 Linux 系统,可以考虑使用一个引导分区

恢复

现在,让我们来看看您精心准备的引导设置可能会出错的地方,特别是在您安装并引导多个操作系统时。要记住的第一件事是控制您最初的恐慌倾向。恢复通常只需几个步骤。这里的战略可以帮助您应对许多类型的危机。

任何能够物理地访问机器的人都拥有许多权力。同样地,任何能够访问 GRUB 命令行的人也能够访问您系统的文件,即使他并没有运行系统所提供的所有权或其他安全供应。在选择引导加载程序时,请牢记这几点。选择 LILO、GRUB 还是 GRUB 2 从很大程度讲是个人偏好问题,尽管 GRUB 2 已经成为主导。 选择最能满足您的特殊需求和工作风格的加载程序。

另一次安装毁坏了您的 MBR

安装另一个操作系统时,可能会无意中覆盖您的 MBR。 一些系统(比如 DOS 和 Windows)会始终安装自己的 MBR。这种情况通常很容易恢复。如果养成每次运行 lilo、重新安装 GRUB 或更新 GRUB 2 时都创建一个恢复软盘、USB 闪存驱动器或 CD 的习惯,就会避免许多烦恼。 可以从软盘引导进入 Linux 系统,并适当地重新运行 lilogrub-installgrub2-install

如果没有自己的恢复介质,但有几乎所有 Linux 发行版的实时或安装介质,那么您可以使用发行版介质或实时介质的恢复模式来修复损坏的 MBR,或者像本教程中所做的那样构建恢复介质。

您移动了一个分区

如果移动了一个分区,但忘记了您的引导设置,您会遇到一个临时问题。通常,LILO 或 GRUB 会拒绝加载。LILO 可能会打印一个 ‘L’ 来表明阶段 1 加载程序已加载,然后停止加载。 GRUB 会提供一条错误消息。这里出现的情况是,阶段 1 加载程序(它有一个要加载到阶段 2 加载程序的扇区的列表)可能从它拥有的地址加载扇区,但这些扇区不再拥有阶段 2 的签名。和毁坏了 MBR 的情况一样,您需要重新安装引导加载程序,所以可以像我介绍的那样使用您的恢复 CD 或 Linux 发行版。

您可能已经注意到,配置示例对您在 清单 1 中看到的分区使用了一些通用唯一标识符 (UUID)(例如,清单 17 中显示的代码段)。

清单 17. 使用 UUID
title CentOS (2.6.32-504.23.4.el6.x86_64)
	root (hd0,10)
	kernel /boot/vmlinuz-2.6.32-504.23.4.el6.x86_64 ro \
           root=UUID=2f60a3b4-ef6c-4d4c-9ef4-50d7f75124a2 rd_NO_LUKS rd_NO_LVM \
           LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=128M \
           KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
	initrd /boot/initramfs-2.6.32-504.23.4.el6.x86_64.img

在 UUID 出现之前,还可以使用 e2label 命令或分区工具(比如 gparted)为 MBR 分区分配一个标签。这些标签与分区移动之间具有一定的独立性。

在移动分区时,我常常使用这样的 UUID 来帮助避免问题。您仍然需要更新 GRUB 或 LILO 配置文件并重新运行 lilo,但不需要再更新 /etc/fstab。如果在一个系统上创建一个分区映像,并将它还原到另一个系统上的不同位置,这非常方便。如果从一个可能没有始终附加到同一个位置的驱动器(比如 USB 驱动器)进行引导,这也很方便。

可以使用 blkid 命令显示磁盘的标签(如果有)和 UUID,如 清单 18 所示。如您所见,我的一些分区使用了标签,一些没有。

清单 18. 显示分区的标签和 UUID
ian@attic-u14:~$ sudo blkid
/dev/sda1:LABEL="/grubfile" UUID="3c3de27e-779a-44d5-ad7a-61c5fd03d9e7" TYPE="ext3" 
/dev/sda2:UUID="158d605e-2591-4749-bf59-5e92e1b1c01d" TYPE="swap" 
/dev/sda3:UUID="ff0b87d2-6929-45df-88e1-d6d3e5cf3d6f" TYPE="ext4" 
/dev/sda5:LABEL="FEDORA22" UUID="7aefe7a0-97d5-45ec-a92e-00a6363fb1e4" TYPE="ext4" 
/dev/sda6:UUID="78a8c7de-cb86-45fe-ac04-be67ef52cb12" TYPE="ext4" 
/dev/sda7:LABEL="FEDORA 18" UUID="1b441a69-63e3-4771-a06b-5efecd1df07e" TYPE="ext4" 
/dev/sda8:LABEL="SUSE13-2" UUID="49d87897-791e-4e48-9efb-704eac447e43" SEC_TYPE="ext2" TYPE="ext3" 
/dev/sda9:UUID="10e82894-186f-4223-95c8-3468eb9b085d" SEC_TYPE="ext2" TYPE="ext3" 
/dev/sda10:LABEL="FEDORA20-64" UUID="8e6e2ebd-20b9-46e8-865f-893dd88c3206" TYPE="ext4" 
/dev/sda11:UUID="2f60a3b4-ef6c-4d4c-9ef4-50d7f75124a2" SEC_TYPE="ext2" TYPE="ext3" 
/dev/sda12:LABEL="UBUNTU-1404" UUID="943524cc-19a9-4237-ac9e-5c1a61a131e3" TYPE="ext4" 
/dev/sdb1:LABEL="GRUB-DATA" UUID="a36a3539-8393-4940-a893-472e9e1c868e" SEC_TYPE="ext2" TYPE="ext3" 
/dev/sdb2:LABEL="DATA-IAN" UUID="4c962b67-c646-467f-96fb-cbbd6de40140" TYPE="ext4" 
/dev/sdb3:LABEL="RESEARCH" UUID="0998d33c-3398-463d-b0e3-7c13ca0c675f" TYPE="ext3" 
/dev/sdb4:UUID="86ad1df3-fea4-47e5-bfdd-fb09f6c2e64a" TYPE="ext4" 
/dev/sdc1:LABEL="PICTURES" UUID="e3be4658-b79b-470d-82fe-bb434bcdcc2f" TYPE="ext4" 
/dev/sr0:LABEL="ISOIMAGE" TYPE="iso9660"

GRUB 2 现在会生成使用旧设备名称作为提示的配置文件,但根设备实际上是基于 UUID(或标签)进行设置的。 请查阅 GRUB 2 手册了解更多的细节。清单 19 中显示了我之前为其构建了一个配置文件的 Ubuntu 14 系统的示例代码段。将根设备初步设置为 'hd0,msdos12' 后,随后的逻辑会使用 search 命令和一些提示来查找根设备的实际位置(如果未执行任何更改,该位置将为 /dev/sda12)。

清单 19. 使用 GRUB 2 根据 UUID 查找根设备
set root='hd0,msdos12'
if [ x$feature_platform_search_hint = xy ]; then
  search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos12 --hint-efi=hd0,msdos12 \
    --hint-baremetal=ahci0,msdos12  943524cc-19a9-4237-ac9e-5c1a61a131e3
else
  search --no-floppy --fs-uuid --set=root 943524cc-19a9-4237-ac9e-5c1a61a131e3
fi

您之前在从恢复闪存驱动器引导时,看到过此代码的使用。 请记住,闪存驱动器变成了 (hd0),第一个硬盘驱动器变成了 (hd1)。

除了这里提到的方法和工具之外,网络上还有一些恢复和引导包。这些包通常包含某个可引导系统和一些有用的恢复工具。示例包括 Knoppix 等包和系统急救 CD(参见参考资料来获取链接,或者在网络上搜索这些包的许多精彩评论之一)。

使用引导分区

另一种恢复(或者可能是避免恢复的)方法是使用一个合适的分区来引导。您刚才已经看到,对系统更改而言,GRUB 2 已变得更加灵活。但是,对于 GRUB Legacy 和 LILO,如果您有一个测试系统,其中包含多个您可能频繁地重新构建的发行版,引导分区可能特别有用。引导分区不需要很大,大约 100MB 左右就够用了。将此分区放在某个不可能移动的地方,以及不可能通过添加或删除另一个分区来改变它的分区编号的地方。在 Windows 和 Linux 混合环境中,/dev/sda2(或 /dev/hda2,具体情况取决于磁盘的标记方式)通常是引导分区的不错选择。事实上,您之前看到的 清单 1 显示了我在自己的系统上使用的小型引导分区 (/dev/sda1) 中的条目。

尽管出于本教程的目的,我添加了一个条目来直接引导进入 CentOS,但我平常的战略是保持条目简单,使用它们链式加载另一个引导加载程序,或者加载 GRUB 2 core.img 文件。 您在 从 GRUB Legacy 引导 GRUB 2,反之亦然 部分看到的示例使用了这个简单的战略。如果使用直接引导进入某个特殊内核的条目,只要更新了目标系统,就需要手动更新这些条目。尽可能地避免额外的工作。图 8显示了我的简单的 GRUB 菜单。

图 8. 一个简单的 GRUB 引导分区菜单

对于此分区,我使用了一个自定义的初始图像,这是使用我在科罗拉多州大沙丘国家公园拍摄的一张照片制作的。请查阅手册页或进行在线搜索,了解创建自己的初始图像的更多信息。图 9显示了使用 /etc/grub.d/40_custom 文件添加到我的 Fedora 22 GRUB 2 菜单末尾处的条目。

图 9. 来自 GRUB 2 的 GRUB 的链式加载器条目

在引导分区使用一个不受引导加载程序支持的文件系统时,需要拥有一个引导分区。例如,在根分区 (/) 使用 LVM(它不受 GRUB Legacy 支持)时,通常会有一个 ext2 或 ext3 格式的 /boot 分区。

如果系统上有多个发行版,不要在它们之间共享 /boot 分区。记得将 LILO 或 GRUB 设置为从以后挂载为 /boot 的分区进行引导。还请记住,一个发行版的更新程序通常会更新系统的 GRUB 或 LILO 配置。在包含多个系统的环境中,您可能想将一个拥有自己的 /boot 分区的系统保留为主系统,在更新另一个系统需要使用它时,再手动更新它的配置文件。另一种方法是让每个系统将一个引导加载程序安装在自己的分区引导记录中,让您的主系统链式加载各个系统的分区引导记录,为您提供一个类似我所使用的流程的两阶段 (two-stage) 菜单流程。

UEFI 和 GPT 考虑因素

尽管本教程重点介绍了 MBR 格式的驱动器,但许多概念仍适用于 GPT 格式的驱动器。UEFI 固件与 BIOS 有很大的区别,而且功能强大得多。当然,它也带来了新的挑战。新功能之一是安全引导 的概念,它只允许经过签名的二进制文件进行引导。许多 UEFI 系统仍支持传统模式 (legacy mode) 引导,这使得旧系统能够在硬件上进行引导。 Windows 8 需要 UEFI 和安全引导,以及 GPT 格式的磁盘,所以如果想要与 Windows 8 或更高版本一起安装,需要对 UEFI 和安全引导有一定的了解。

一些实时 Linux 发行版(比如 Ubuntu 和 Fedora)和它们的衍生版本支持在启用了安全引导的 UEFI 系统上进行引导。建立信任链的方法在 Linux 内核开发社区中存在一些争议。我将介绍如何将 Ubuntu 15.04 发行版 ISO 映像解包到一个 USB 闪存驱动器上,让您可以了解该设置。

对于本练习,我使用了一个 Ubuntu 14 系统,将一个小型 USB 闪存驱动器格式化为 GPT,然后创建一个 2GB 的分区,如 清单 20 所示。我将该分区格式化为 FAT32,因为 UEFI 固件需要 FAT32 分区中的一些文件。请小心使用正确的设备;您的设备可能不在 /dev/sdf 上。

清单 20. 准备一个 GPT 格式的 USB 闪存驱动器
ian@attic-u14:~$ sudo parted /dev/sdf
GNU Parted 2.3
Using /dev/sdf
Welcome to GNU Parted!Type 'help' to view a list of commands.
(parted) mklabel gpt
Warning:The existing disk label on /dev/sdf will be destroyed and all data on
this disk will be lost.Do you want to continue?
Yes/No?yes                                                               
(parted) mkpart primary fat32 1MB 2048MB                                  
(parted) toggle 1 boot                                                  
(parted) print                                                            
Model:USB DISK 2.0 (scsi)
Disk /dev/sdf:15.5GB
Sector size (logical/physical):512B/512B
Partition Table  : gpt

Number  Start   End     Size    File system  Name     Flags
 1      1049kB  2048MB  2047MB  fat32        primary  boot

(parted) quit                                                             
Information:You may need to update /etc/fstab.                           

ian@attic-u14:~$ sudo mkfs.fat -F 32 /dev/sdf1
mkfs.fat 3.0.26 (2014-03-07)

在准备好闪存驱动器后,需要挂载它。然后,需要将 Ubuntu 15 ISO 映像解包到这个闪存驱动器上。清单 21显示了您实现此目标的许多可能方法之一。

清单 21. 将 Ubuntu 15 解包到一个实时 USB 映像
ian@attic-u14:~$ sudo mkdir /mnt/u15iso /mnt/flashdrive
ian@attic-u14:~$ sudo mount ~/Downloads/ubuntu-15.04-desktop-amd64.iso /mnt/u15iso/ -o ro,loop=/dev/loop1
ian@attic-u14:~$ sudo mount /dev/sdf1 /mnt/flashdrive/
ian@attic-u14:~$ sudo rsync -a -H /mnt/u15iso/ /mnt/flashdrive
rsync: symlink "/mnt/flashdrive/ubuntu" -> "." failed:Operation not permitted (1)
rsync: symlink "/mnt/flashdrive/dists/stable" -> "vivid" failed:Operation not permitted (1)
rsync: symlink "/mnt/flashdrive/dists/unstable" -> "vivid" failed:Operation not permitted (1)
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at \
main.c(1183) [sender=3.1.0]
ian@attic-u14:~$ diff -rq /mnt/u15iso/ /mnt/flashdrive
Only in /mnt/u15iso/dists: stable
Only in /mnt/u15iso/dists: unstable
Only in /mnt/u15iso/: ubuntu
i

在卸载闪存驱动器之前,请查看它之上的一些文件。如果列出根目录,就会看到两个目录 EFI 和 boot,还有其他一些文件和目录。根目录是您的 GRUB 2 引导目录,而 EFI 目录是 UEFI 固件搜索要引导的已签名二进制文件的目录。这个目录必须有一个 FAT 文件系统(或 CD 上的 ISO 9660 文件系统)。这正是我将该分区格式化为 FAT32 的原因。 清单 22 显示了这些文件。您现在可以卸载并弹出闪存驱动器,尝试在一个同时启用了安全引导和禁用了传统引导的系统上引导它。

清单 22. 检查闪存驱动器上的根目录
ian@attic-u14:~$ ls /mnt/flashdrive/
autorun.inf  casper  EFI      isolinux    pics  preseed             wubi.exe
boot         dists   install  md5sum.txt  pool  README.diskdefines
ian@attic-u14:~$ ls /mnt/flashdrive/EFI
BOOT
ian@attic-u14:~$ ls /mnt/flashdrive/EFI/BOOT/
BOOTx64.EFI  grubx64.efi
ian@attic-u14:~$ umount /mnt/flashdrive 
umount:/mnt/flashdrive is not in the fstab (and you are not root)
ian@attic-u14:~$ sudo umount /mnt/flashdrive 
ian@attic-u14:~$ sudo eject /dev/sdf
i

要在只启用了安全引导和 UEFI 引导的 Windows 8 系统上进行引导,可能需要禁用快速引导,因为这会导致从 semi-hibernat3ed 模式重新引导。还需要知道如何从 USB 闪存驱动器等设备进行引导。完成两项任务的一种方法是使用 Windows 恢复环境(参见 参考资料)。访问此环境的一种方法是在正在运行的 Windows 8 系统上启动关机序列,然后按住 shift 键并单击 Restart。图 10显示了我在我的 Lenovo Yoga 2 笔记本电脑上看到的屏幕。

图 10. 在 Windows 8.1 中重新引导到一个 USB 闪存驱动器
Reboot to a USB flash drive in Windows 8.1
Reboot to a USB flash drive in Windows 8.1

在我在系统上选择 Use a device 后,下一个提示允许我选择一个 EFI USB 设备。 从类似这样的一个提示符,您可以引导刚创建的闪存驱动器。

在引导您的 Ubuntu 系统后,可以挂载您的 Windows 8 系统的 EFI 分区并检查它。在我的例子中,该分区是 /dev/sda2。清单 23显示了此分区上的 EFI 目录。

清单 23. /dev/sda2 上的 Windows 8.1 EFI 目录
ubuntu@ubuntu:~$ sudo mkdir /mnt/sda2
ubuntu@ubuntu:~$ sudo mount /dev/sda2 /mnt/sda2/
ubuntu@ubuntu:~$ ls /mnt/sda2
BOM.BAT  BOOT  EFI
ubuntu@ubuntu:~$ ls /mnt/sda2/EFI/
Boot  Microsoft
ubuntu@ubuntu:~$ ls /mnt/sda2/EFI/Boot/
bootx64.efi

同样地,您可以找到一个 bootx64.efi 可执行文件,UEFI 固件知道在何处寻找它。

结束语

您已经学习了传统 Linux 系统的主要引导加载程序,包括如何从错误和引导问题中恢复。您还简单了解了 UEFI 引导和引导问题。


下载资源


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Linux, Open source
ArticleID=1024361
ArticleTitle=学习 Linux,101: 安装引导管理器
publish-date=12162015