学习 Linux,101: 引导管理器

GRUB、GRUB 2 和 LILO 简介

了解如何为您的 Linux 系统选择和配置一个引导程序。您可以使用本文中的资料来学习,为参加 Linux 系统管理员认证的 LPI 101 考试而做准备,当然也可以是出于爱好而学习。

2012 年 12 月 4 日 - 本文做了一些更新,以包含适用于 LPI Exam 101: Objective Changes as of July 2, 2012 的资料。

主要更新包括 GRUB 2 小节中的 GRUB 2 新信息,以及 GRUB 2 的恢复镜像 小节的 GRUB 2 恢复镜像和闪存驱动器的使用。LPI 已经从目标中删除了 LILO,所以 LILO 小节出现在了本文的后半部分。其他小节包含一些反映 GRUB 2 的微小更新,它们是目标和修订内容订单的一部分。

Ian Shields, 高级程序员, IBM

Ian ShieldsIan Shields 参与 developerWorks Linux 专区的许多 Linux 项目。他是 IBM 北卡罗来纳州 Research Triangle Park 的一名高级程序员。他于 1973 年作为一名系统工程师加入 IBM 位于澳大利亚堪培拉市的子公司。此后,在加拿大蒙特利尔和北卡罗来纳州 RTP 从事通信系统和普及运算。他拥有多项专利并发表了多篇论文。他毕业于 Australian National University,本科学位是纯数学和哲学。他拥有北卡罗来纳州州立大学的计算机硕士和博士学位。要详细了解 Ian,请查看 Ian 在 My developerWorks 上的个人资料



2013 年 1 月 17 日 (最初于 2010 年 4 月 13 日)

关于本系列

本系列文章帮助您了解 Linux 系统管理任务。您可以使用本系列文章中的资料准备 Linux Professional Institute Certification 级别 1 (LPIC-1) 考试

请参见我们的 LPIC-1 developerWorks 路线图 查看本系列中各文章的介绍和链接。 该路线图目前仍然在更新中,目前反映的最新内容是 LPIC-1 考试的最新目标(2009 年 4 月,在 2012 年 7 月做过少许更新):在完成文章后,我们会将其添加到路线图中。但是,与此同时,您可以在我们的 LPI 认证考试准备教程 中找到类似资料的早期版本,这些内容支持 2009 年 4 月以前发布的 LPIC-1 目标。

概述

在本文中,学习为一个 Linux 系统选择、安装和配置引导管理器。您将学习:

  • 配置多个引导位置和备份引导选项
  • 安装和配置一个启动加载程序,比如 GRUB、GRUB 2 或 LILO
  • 在启动时添加引导参数或运行启动加载程序命令
  • 恢复常见引导问题
  • 使用 GRUB Legacy 引导 GRUB 2 系统

本文将讨论 PC 启动过程和 Linux 中使用的 3 个主要启动加载程序:GRUB、GRUB 2 和 LILO,它们可以帮助您准备 Linux Professional Institute's Junior Level Administration (LPIC-1) 考试 101 中主题 102 下的目标 102.2。 该目标的权值为 2。请注意,LPIC-1 不再要求掌握 LILO。本文包含 LILO 内容以便于您对其有所了解。

先决条件

为了最有效地利用本系列中的文章,您应该具有基本的 Linux 知识,并准备一个 Linux 系统,用于练习本文介绍的命令。您还应该熟悉文章 “学习 Linux 101:硬盘布局” 中讨论的硬盘驱动器布局。有时候不同版本的程序输出格式不同,因此您所得到的结果未必总是与这里所示的清单和图相同。

注意:本文中的图像是从启动过程初期采集的屏幕截图。如果您正在使用一个屏幕读取器阅读本文,您可能会发现拥有对应的配置文件以便参考的好处;从本文后面的 下载 部分下载它们。


启动过程概述

联系 Ian

Ian 是我们最受欢迎且多产的作者之一。阅读 Ian 在 developerWorks 上 发表的所有文章。查看Ian 的个人资料,并与他和 developerWorks 社区中的其他作者和读者联系。

在深入了解具体启动加载程序之前,先回顾一下如何启动或引导 PC。名为 BIOS(表示 Basic Input Output Service)的代码存储在一个非临时内存中,比如 ROM、EEPROM 或闪存。当打开或重新启动 PC 时,会执行这个代码。通常,它执行一个启动自测 (POST) 来检查机器。最后,它从引导驱动器上的主引导记录(MBR)加载第一个扇区。

正如文章 “学习 Linux 101:硬盘布局” 所述,MBR 还包含分区表,因此 MBR 中的可执行代码小于 512 字节,这个代码量不算多。注意,每个磁盘(甚至是软盘))都在它的 MBR 中包含可执行代码,即使这个代码只够输出一条消息,比如 “Non-bootable disk in drive A:(驱动器 A 中没有可引导磁盘:)”。这个由 BIOS 从第一扇区加载的代码称为第一阶段启动加载程序阶段 1 启动加载程序

开发此方面的技能

本内容是一套渐进的学习路线图的一部分,用来帮助您提升自己的技能。请参考 Linux 系统管理基础:设置您的系统和软件

MS DOS、PC DOS 和 Windows® 操作系统使用的标准硬盘驱动器 MBR 会检查分区表,以查找标记为 active 的引导驱动器上的主分区,从该分区加载第一个扇区,然后将控制权交给已加载的代码。这个新的代码片段也称为分区引导记录。分区引导记录实际上是阶段 1 的另一个启动加载程序,但它只能从分区加载一组块。该新组块中的代码称为阶段 2 启动加载程序。MS-DOS 和 PC-DOS 使用的阶段 2 加载程序直接继续加载操作系统其余部分。以上就是操作系统启动并运行的引导进程。

这个引导进程对于单操作系统很适用。但是,如果您想要使用多个操作系统,比如 OS/2、Windows XP 和 3 个不同的 Linux 发行版,那么会出现什么样的情况呢?您可以 使用某个程序(比如 DOS FDISK 程序)来更改活动分区并重新启动,但这种方法比较笨拙。此外,一个磁盘只能拥有 4 个主分区,而标准 MBR 只能拥有一个主分区;系统不能从逻辑分区引导。但我们假设的示例提到了 5 种操作系统,每个系统都需要一个分区。

该问题的解决方案是使用一些特殊代码,允许用户选择引导哪个操作系统。此类程序包括:

Loadlin
一个 DOS 可执行程序,可以在一个正在运行的 DOS 系统中调用它来引导一个 Linux 分区。如果多引导系统的设置过程很复杂且存在风险,那么这个代码就能够派上用场。
OS/2 Boot Manager
这个程序安装在一个专用小分区上,分区被标记为 active,标准 MBR 引导进程启动 OS/2 Boot Manager,该程序显示一个菜单,允许选择要启动的操作系统。
智能启动加载程序
该程序可以驻留在操作系统的分区上,通过一个活动分区的分区引导记录或主引导记录进行调用。这类程序包括:
  • BootMagic,Norton PartitionMagic 的一部分
  • LILO,即 LInux LOader
  • GRUB,即 GRand Unified Boot 加载程序 (现在称为 GRUB Legacy)
  • GRUB 2,最近才在常用发行版中出现的一个新的启动加载程序

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

链式加载

当一个引导管理器获得控制权时,它可能做的一件事就是加载另一个引导管理器。这种现象称为链式加载 (chain loading),通常发生在位于主引导记录 (MBR) 中的引导管理器加载一个分区引导记录中的启动加载程序的时候。当一个 Linux 启动加载程序被请求引导一个 Windows 或 DOS 分区时总是需要进行链式加载,或者当一个 Linux 系统(比如 Fedora)的 Linux 启动加载程序被配置来加载另一个 Linux 系统(比如 Ubuntu)的启动加载程序时,可能也需要链式加载。例如,您可能需要使用一个分区中的 GRUB 启动另一个分区引导记录中的 GRUB 启动加载程序,以便在该分区中启动 Linux 系统。 这是并不常见,我们只是列举了这种可能性。

Linux 启动加载程序

从现在开始,我们将主要关注 GRUB、GRUB 2 和 LILO,因为它们是大多数 Linux 发行版包含的启动加载程序。LILO 已经存在一段时间了,而 GRUB 比较新。最初的 GRUB 现在已成为了 GRUB Legacy,GRUB2 正在 Free Software Foundation 的赞助下进行开发(参见 参考资料,了解相关的详细信息)。我们先讨论 GRUB、然后讨论 GRUB2,让您对 GRUB 和 GRUB2 之间的主要区别以及二者如何能够共存有一些了解。在本文其余部分中,我们假设 GRUB 是指 GRUB Legacy,除非上下文特别暗指 GRUB 2。LILO 也有一个新版本,称为 ELILO(设计用于引导使用 Intel 而非 BIOS 的 Extensible Firmware InterfaceEFI)。请参见 参考资料,了解关于 GRUB2 和 ELILO 的其他相关信息。

您的发行版的安装过程可能支持选择设置哪个启动加载程序。无论 GRUB、GRUB 2 还是 LILO,都能适应大多数现代磁盘,但是有些版本(最著名的 Fedora)不再包含 LILO。别忘了,磁盘技术已经飞速发展,因此您应该总是确保所选的启动加载程序、Linux 版本(或其他操作系统)以及您的系统 BIOS 适用于您的新磁盘。否则,就有可能导致数据丢失。同样,向现有系统添加新版本时,可能需要确保您的 MBR 中拥有最新的 LILO、GRUB 或 GRUB 2。如果打算从 LVM 或 RAID 磁盘引导,还需要一个较新的启动加载程序版本。

LILO 和 GRUB 中使用的阶段 2 加载程序允许从几个操作系统或版本中选择一个。但是,LILO 和 GRUB 差别很大:只要升级内核或对系统进行其他更改,就需要使用一条命令重新创建 LILO 引导设置;而 GRUB 支持通过一个可编辑配置文本文件来完成这项任务。GRUB2 还需要从一个通常存储在 /etc 中的配置文件执行重构。


GRUB

GRUB(即 GRand Unifood Boot loader)是最常用的 Linux 启动加载程序之一。GRUB 可以安装到您的可引导硬盘驱动器的 MBR 中,或者安装到一个分区的分区引导记录中。它还可以安装到可移动设备中,比如软盘、CD 和 USB 磁盘。如果您还不熟悉 GRUB,那么在一张软盘或 USB 磁盘上进行练习是一个不错的主意,我们将通过示例向您展示具体的操作。

GRUB 或 GNU GRUB,目前是在 Free Software Foundation 的赞助下开发的。作为一个新版本,GRUB 2 还处于开发之中,并开始包含于 Linux 发行版之中,因此原始的 GRUB 0.9x 版本现在称为 Grub Legacy。

在安装 Linux 期间,通常需要指定引导程序。如果您选择 LILO,那么您可能还没有安装 GRUB。如果是这样,那么您必须安装它的安装包。从此刻起,我们假定您已经安装了 GRUB 包。如果需要帮助,请参阅我们的 路线图系列,获取关于安装包管理的文章。

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

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 开始对驱动器、分区和其他需要计数的东西进行计数的。还要注意的是,第一个内核行非常长。对于发行版,我们使用一个反斜杠(\)来指出何处需要中断。

清单 1. /boot/grub/menu.lst GRUB 配置示例
# grub.conf generated by anaconda
#
# Note that 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/sda6
#          initrd /boot/initrd-version.img
#boot=/dev/sda6
default=1
timeout=10
splashimage=(hd0,5)/boot/grub/splash.xpm.gz
#hiddenmenu
password --md5 $1$RW1VW/$4XGAklxB7/GJk0uO47Srx1
title Upgrade to Fedora 11 (Leonidas)
	kernel /boot/upgrade/vmlinuz preupgrade \ 
      repo=hd::/var/cache/yum/preupgrade stage2=\
      hd:UUID=8b4c62e7-2022-4288-8995-5eda92cd149b:/boot/upgrade/install.img \
      ks=hd:UUID=8b4c62e7-2022-4288-8995-5eda92cd149b:/boot/upgrade/ks.cfg
	initrd /boot/upgrade/initrd.img
title Fedora (2.6.26.8-57.fc8)
	root (hd0,5)
	kernel /boot/vmlinuz-2.6.26.8-57.fc8 ro root=LABEL=FEDORA8 rhgb quiet
	initrd /boot/initrd-2.6.26.8-57.fc8.img
title Fedora (2.6.26.6-49.fc8)
	root (hd0,5)
	kernel /boot/vmlinuz-2.6.26.6-49.fc8 ro root=LABEL=FEDORA8 rhgb quiet
	initrd /boot/initrd-2.6.26.6-49.fc8.img
title GRUB Menu
	rootnoverify (hd0,1)
	chainloader +1
title Windows
	rootnoverify (hd0,0)
	chainloader +1

上述第一组选项控制 GRUB 的操作方式。对于 GRUB 来说,这些命令称之为菜单命令,它们必须出现在其他命令前面。本小节其余部分将为我们允许 GRUB 引导的操作系统提供每映像 (per-image) 选项。请注意,“title” 被认为是一个菜单命令。每个标题实例后面有一个或多个一般或菜单项命令。我们的 GRUB 示例是一个典型的包含 Windows 和两个 Linux 系统的双引导系统的基础示例。该示例来自于我们前面使用的同一个系统。事实上,它是从 LILO 菜单中的 “Fedora 8” 链式加载而来的启动菜单。您会发现,许多类型相同的元素同时出现在 LILO 和 GRUB 配置文件中。您可能会思考这样一个问题:如果将该额外操作系统添加到前面的 LILO 示例中,需要进行哪些更改?

示例中的所有其他部分应用的菜单命令包括:

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

我们的示例展示了两个 Fedora 8 内核和一个升级到 Fedora 11 的选项,以及 Windows XP 和一个链式加载的 “GRUB Menu” 选项。这些小节中使用的命令有:

title
一个描述性标题,当 Grub 启动时显示为菜单项。使用方向键上下移动标题列表并按 Enter 键选择一个特定项。
root
指定将要启动的分区。与 splashimage 一样,从 0 开始计数,因此指定为 root (hd0,6) 的第一个 Red Hat 系统实际上是在第一个硬盘驱动器的第 7 个分区上(本例中为 /dev/hda7),而指定为 root (hd1,10) 的第一个 Ubuntu 系统位于第二个硬盘驱动器上。GRUB 将尝试加载这个分区以检查它,并在某些情况下向已启动操作系统提供一些值。
kernel
指定将被加载的内核映像以及所需内核参数。这类似于 LILO 映像append 命令的组合,您将在 LILO 小节看到该命令。在本例中,有两个不同的 Fedora 8 内核,以及升级内核。
initrd
初始 RAM 磁盘 的名称,包含文件系统挂载之前内核需要的模块。
savedefault
本示例中不使用。如果指定了菜单命令 default=saved,并为一个操作系统指定了 savedefault 命令,那么引导该操作系统将导致它变为默认值,直至启动带有指定 savedefault 的另一个操作系统。在这个示例中,default=2 将覆盖保存的所有默认值。
boot
一个可选参数,指示 GRUB 启动选择的操作系统。当一个选项所有命令全部执行完时,这将是一个默认操作。
lock
本示例中不使用。没有输入密码之前不会启动指定项。如果使用这个命令,那么还应该在初始选项中指定一个密码;否则,用户可以编辑您的锁定选项并启动系统,或者添加 “single” 到其中的一项。如果您愿意的话,还可以为个别条目指定一个不同的密码。
rootnoverify
类似于 root,除非 GRUB 不尝试挂载文件系统或验证其参数。这通常用于 GRUB 不支持的文件系统,比如 NIFS。如果您想要 GRUB 加载硬盘驱动器上的主引导记录,也可以使用这个命令,例如,访问不同的配置文件或者重新加载您之前的启动加载程序。
chainloader
指定将作为阶段 1 文件加载的另一个文件。值 “+1” 等同于 0+1,表示加载从扇区 0 开始的一个扇区,即,从 root 或 rootnoverify 指定的设备加载第一个扇区。

现在,您已经对一个典型的 /boot/grub/grub.conf(或 /boot/grub/menu.lst)文件中可能包含的内容有所了解。还有其他许多 GRUB 命令可以提供对启动过程的广泛控制,帮助安装 GRUB 和完成其他任务。您可以在 GRUB 手册中了解关于这些命令的更多信息,可以通过在您的系统上运行 info grub 命令来获取这个手册。

现在我们已经有了一个 GRUB 配置文件,需要创建一个启动软盘来测试它。最简单的方法是使用 清单 2 中展示的 grub-install 命令。如果您正在将 GRUB 安装到一个软盘或一个分区上,那么您应该首先卸载该设备。这不适用于将 GRUB 安装到一个硬盘驱动器的 MBR 上,因为您只是挂载分区(/dev/sda1、/dev/sda2 等)而不是挂载整个硬盘驱动器 (/dev/sda)。

清单 2. 将 GRUB 安装到软盘上
[root@pinguino ~]# grub-install /dev/fd0
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

注意:您可能使用 GRUB 设备名 (fd0) 而不是 /dev/fd0,如果您的确那样做,则必须用引号括起来,以免 shell 将其解释为圆括号。例如:grub-install '(fd0)'

设备映射告诉您 GRUB 如何将磁盘 (fd0, hd0, hd1) 的内部视图与 Linux 视图 (/dev/fd0, /dev/sda, /dev/sdb) 相匹配。在带有一个或两个 IDE 硬盘驱动器以及可能还有一个软盘驱动器的系统上,这可能是正确的。但如果一个设备映射已经存在,那么 GRUB 将重新使用它,无需探测。如果您只是添加一个新驱动器并想强制生成一个新设备映射,那么添加 --recheck 选项到 grub-install 命令。有时,您可能会看到一条如 清单 3 所示的消息。该示例中也同样,您还需要添加 --recheck 选项到 grub 命令,以强制 GRUB 探测可用设备并重新构建一个设备映射。

清单 3. 将 GRUB 安装到软盘
[root@pinguino ~]# grub-install /dev/fd0
/dev/fd0 does not have any corresponding BIOS drive.

如果您使用一张空白软盘开始并且现在开始挂载,那么您将发现该软盘现在仍然是空的。现在的情况是 GRUB 将一个自定义的阶段 1 加载程序写入该软盘的第一个扇区。这并不在文件系统中显示。这个阶段 1 加载程序将从您的硬盘驱动器上加载阶段 2 和配置文件。尝试启动软盘,在菜单显示之前很少能看到 IO 活动。使用上移和下移箭头来选择不同的引导目标。

图 1. 使用 GRUB 引导
终端窗口屏幕截图显示了不同引导目标

测试完您的启动软盘后,就可以在硬盘驱动器的 MBR 中安装 GRUB 了。对于第一个 IDE 硬盘驱动器,您应该使用:
grub-install /dev/sda

grub-install '(hd0)'

要将它安装到分区 11 的分区引导记录中,使用:
grub-install /dev/sda11

grub-install '(hd0,10)'

别忘了 GRUB 从 0 开始计数。

您可以向该命令添加引导参数。事实上,您可以编辑 GRUB 配置中的任何命令,或者甚至在引导时加载另一个配置文件。如果您使用一个密码,您将需要输入 p 命令,然后输入您的密码。然后,选择一个条目并输入 e 命令对其进行编辑。选择想要编辑的行并再次输入 e。通过输入新的字符或删除现有字符编辑该行,然后按 Enter 键返回菜单。输入 b 命令来使用修改值启动您的系统。图 2 展示了该过程的命令编辑阶段,其中您将 “single” 参数添加到内核语句以引导到单用户模式。

图 2. 使用 GRUB 引导到单用户模式
终端窗口屏幕截图显示了命令编辑阶段

GRUB 2

GRUB 2 是完全重新编写的,以便使其更模块化且可移植。它面向多个不同的基础架构和引导方法,拥有许多新特性。请参见 参考资料 中的链接,了解有关的更多信息。如果您过去使用的是 GRUB,现在才开始使用 GRUB 2,您会发现它们完全不同,可能会获得很多惊喜。

关于 GRUB 2,您可能注意到的第一点就是它不能作为一个分区启动加载程序安装。尽管我告诉 Ubuntu 安装者将 GRUB 安装在已安装 Ubuntu 9.10 的分区(/dev/sda7)上,但是该分区不能通过链式加载启动。本小节其余部分将简要介绍 GRUB 2,这些信息足以帮助您开始使用它,无论是单独使用还是与 GRUB Legacy 结合使用。

适用于 PC 机的 GRUB 2 版本分布在 grub-pc 软件包中。您会发现几个程序,它们通常位于 /usr/bin 或 /usr/sbin 中,这些程序是 grub-pc 软件包的一部分,如 清单 4 所示。在本文撰写之时,这些程序的手册页很少。尝试使用 --help 选项来运行这些程序以获得更多信息,或者在网上搜索其他帮助。

清单 4. /usr/bin 和 /usr/sbin 中的 GRUB 2 可执行文件
ian@pinguino:~$ dpkg -L grub-pc|grep "bin/"
/usr/bin/grub-mkimage
/usr/bin/grub-mkrescue
/usr/sbin/grub-setup
/usr/sbin/update-grub2
/usr/sbin/update-grub
/usr/sbin/grub-install
/usr/sbin/upgrade-from-grub-legacy
/usr/sbin/grub-set-default
/usr/sbin/grub-reboot

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

清单 5. grub-install 的 GRUB 2 帮助
ian@pinguino:~$ grub-install --help
Usage: grub-install [OPTION] install_device
Install GRUB on your drive.

  -h, --help              print this message and exit
  -v, --version           print the version information and exit
  --modules=MODULES       pre-load specified modules MODULES
  --root-directory=DIR    install GRUB images under the directory DIR
                          instead of the root directory
  --grub-setup=FILE       use FILE as grub-setup
  --grub-mkimage=FILE     use FILE as grub-mkimage
  --grub-mkdevicemap=FILE use FILE as grub-mkdevicemap
  --grub-probe=FILE       use FILE as grub-probe
  --no-floppy             do not probe any floppy drive
  --recheck               probe a device map even if it already exists
  --force                 install even if problems are detected
  --disk-module=MODULE    disk module to use

INSTALL_DEVICE can be a GRUB device name or a system device filename.

grub-install copies GRUB images into the DIR/boot directory specified by
--root-directory, and uses grub-setup to install grub into the boot
sector.

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

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

构建 GRUB 2 核心映像

构建一个新核心映像文件的最简单的方法是运行带有 --grub-setup=/bin/true 选项的 grub-install 命令,这将导致 /bin/true 而不是真正的 GRUB 2 安装程序运行,如 清单 6 所示。我们首先删除现有的 core.img,以便展示真的生成了这个文件。

清单 6. 使用 grub-install 构建 GRUB 2 核心映像
ian@pinguino:~$ sudo rm /boot/grub/core.img 
ian@pinguino:~$ sudo grub-install --grub-setup=/bin/true /dev/sda
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'.

(hd0)	/dev/sda
ian@pinguino:~$ ls -l /boot/grub/core.img
-rw-r--r-- 1 root root 25105 2010-04-08 12:10 /boot/grub/core.img

构建 GRUB 2 配置文件

GRUB 2 配置文件通常是 /boot/grub/grub.cfg。与 GRUB Legacy 不同,您通常不应该编辑这个文件,而应该使用 grub-mkconfigupdate-grub 命令(该命令是 grub-mkconfig 的前端)来构建它。这些命令在 /etc/default/grub 中寻找背景、超时等等,然后运行 /etc/grub.d/ 中的可执行文件来构建配置文件的各个部分,比如头文件、一个针对当前 Linux 发行版的区域、几个针对其他操作系统的区域、以及您自己的自定义增加项。如果您需要定制 GURB 2 菜单,那么应该将您的更改添加到 /etc/grub.d/ 下的一个文件(比如 40_custom)中,或者添加您自己的文件中。记住,该文件必须是可执行文件。然后,运行 update-grub 生成一个新的 /boot/grub/grub.cfg 文件,如 清单 7 所示。

清单 7. 使用 update-grub 构建一个 GRUB 2 配置文件
ian@pinguino:~$ sudo update-grub
Generating grub.cfg ...
Found linux image: /boot/vmlinuz-2.6.31-20-generic
Found initrd image: /boot/initrd.img-2.6.31-20-generic
Found linux image: /boot/vmlinuz-2.6.31-14-generic
Found initrd image: /boot/initrd.img-2.6.31-14-generic
Found memtest86+ image: /boot/memtest86+.bin
Found GRUB boot loader on /dev/sda1
Found Fedora release 8 (Werewolf) on /dev/sda6
done

清单 8 展示了结果配置文件中的几个条目。我们已经说过,为了版面美观,我们使用一个后置反斜杠(\)来分割较长的行。注意,menuentry 小节看起来更像 shell 脚本,而不像不带有 GRUB Legacy 逻辑的纯命令。与 GRUB Legacy 不同的另一个变化是现在分区编号从 1 开始,尽管磁盘编号仍然从 0 开始。因此 /dev/sda7 在 GRUB 2 中是 (hd0,7),而在 GRUB Legacy 中则为 (hd0,6)。

清单 8. GRUB 2 配置文件片段
### BEGIN /etc/grub.d/05_debian_theme ###                               
set menu_color_normal=white/black
set menu_color_highlight=black/white
### END /etc/grub.d/05_debian_theme ###                                 

### BEGIN /etc/grub.d/10_linux ###                                      
menuentry "Ubuntu, Linux 2.6.31-20-generic" {
        recordfail=1
        if [ -n ${have_grubenv} ]; then save_env recordfail; fi
        set quiet=1
        insmod ext2
        set root=(hd0,7)
        search --no-floppy --fs-uuid --set 8954fa66-e11f-42dc-91f0-b4aa480fa103
        linux   /boot/vmlinuz-2.6.31-20-generic \
          root=UUID=8954fa66-e11f-42dc-91f0-b4aa480fa103 ro   quiet splash
        initrd  /boot/initrd.img-2.6.31-20-generic
}
menuentry "Ubuntu, Linux 2.6.31-20-generic (recovery mode)" {
        recordfail=1
        if [ -n ${have_grubenv} ]; then save_env recordfail; fi
        insmod ext2
        set root=(hd0,7)
        search --no-floppy --fs-uuid --set 8954fa66-e11f-42dc-91f0-b4aa480fa103
        linux   /boot/vmlinuz-2.6.31-20-generic 
         root=UUID=8954fa66-e11f-42dc-91f0-b4aa480fa103 ro single
        initrd  /boot/initrd.img-2.6.31-20-generic
}

从 Grub Legacy 启动 GRUB 2

如前所述,您不能从一个分区引导记录链式加载 GRUB 2。但是,当构建核心映像和配置文件之后,就可以将一个条目添加到 GRUB Legacy grub.conf 或 menu.lst 文件,以便启动 GRUB 2 核心映像,该映像随后会显示您构建的 GRUB 2 菜单。清单 9 展示了在 清单 15 中已经使用过的条目。由于这个配置文件适用于 GRUB Legacy,所以 root 条目将 /dev/sda7 指定为 (hd0,6)。

清单 9. 启动 GRUB 2 核心映像的 Grub Legacy 配置条目
# Ubuntu 9.10 uses GRUB 2, so use kernel to drive GRUB 2 menu.          
title           Ubuntu 9.10 (sda7)
root            (hd0,6)
kernel          /boot/grub/core.img

当您从 GRUB Legacy 菜单中选择这个条目时,您会看到一个类似于 图 3 的菜单,其中第一个条目被突出显示,下一个条目在 清单 8 中显示。

图 3. GRUB 2 菜单示例
GRUB 2 菜单示例的屏幕截图

您可能会想要尝试在一个分区引导记录中安装 GRUB 2。如果这样,您可能会看到类似 清单 10 的输出。

清单 10. 尝试将 GRUB 2 安装到一个分区引导记录
ian@pinguino:~$ sudo grub-install /dev/sda7
grub-setup: warn: Attempting to install GRUB to a partition instead of the MBR.  
This is a BAD idea.
grub-setup: warn: Embedding is not possible.  GRUB can only be installed in 
this setup by using blocklists.  However, blocklists are UNRELIABLE and its 
use is discouraged.
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'.

(hd0)	/dev/sda

这解释了当我安装 Ubuntu 9.10 时试图在 /dev/sda7 中安装 GRUB 2 为什么会失败。有一点值得注意,Ubuntu 的这个版本将 GRUB 2 作为一个新安装程序,但如果您正在升级现有的 Ubuntu 安装,它将保留现有的引导程序。


LILO

LILO(即 LInux LOader)是三个最常用的 Linux 启动加载程序之一。您可以将 LILO 安装到您的可引导硬盘驱动器的 MBR 中,或者将它安装到一个分区的分区引导记录中。还可以将它安装到可移动设备上,比如软盘、CD 和 USB 磁盘。如果您还不熟悉 LILO,那么在软盘或 USB 磁盘上练习是一个不错的注意,我们的示例就是这样做的。

在 Linux 安装期间,通常需要指定一个引导管理器。如果您选择 GRUB,您可能没有安装 LILO。如果是这样,那么您必须安装 LILO 安装包。您可能想安装 lilo-doc 安装包,以便获得其他文档和示例。从此刻起,我们假定您已经安装了 LILO 安装包。如果需要帮助,请参阅我们的 路线图系列,获取关于安装包管理的文章。

使用一个配置文件来配置 LILO,这个配置文件通常是 /etc/lilo.conf。可以使用 liloconfig 命令(通常位于 /usr/sbin 中)来生成一个启动配置文件,然后根据需要编辑它。清单 11 中的配置文件就是以这种方式生成的。这个文件的注释比较合理,lilo 和 lilo.conf 的手册页将为您提供更多的帮助。这是一个典型的 LILO 配置文件,可用在包含 Windows 以及一个或多个 Linux 系统的双启动系统上。

清单 11. /etc/lilo.conf 示例
# Originally generated by liloconfig - modified by Ian Shields

# This allows booting from any partition on disks with more than 1024
# cylinders.
lba32

# Specifies the boot device (floppy)
boot=/dev/fd0

# Specifies the device that should be mounted as root.
# If the special name CURRENT is used, the root device is set to the
# device on which the root file system is currently mounted. If the root
# has been changed with  -r , the respective device is used. If the
# variable ROOT is omitted, the root device setting contained in the
# kernel image is used. It can be changed with the rdev program.
root=/dev/sda7

# Bitmap configuration for /boot/coffee.bmp
bitmap=/boot/coffee.bmp
bmp-colors=12,,11,15,,8
bmp-table=385p,100p,1,10
bmp-timer=38,2,13,1

# Enables map compaction:
# Tries to merge read requests for adjacent sectors into a single
# read request. This drastically reduces load time and keeps the map
# smaller. Using COMPACT is especially recommended when booting from a
# floppy disk.
compact

# Install the specified file as the new boot sector.
# LILO supports built in boot sectors, you only need
# to specify the type, choose one from 'text', 'menu' or 'bitmap'.
# new: install=bmp      old: install=/boot/boot-bmp.b
# new: install=text     old: install=/boot/boot-text.b
# new: install=menu     old: install=/boot/boot-menu.b or boot.b
# default: 'menu' is default, unless you have a bitmap= line
# Note: install=bmp must be used to see the bitmap menu.
# install=menu
install=bmp

# Specifies the number of _tenths_ of a second LILO should
# wait before booting the first image.  LILO
# doesn't wait if DELAY is omitted or if DELAY is set to zero.
# delay=20

# Prompt to use certain image. If prompt is specified without timeout,
# boot will not take place unless you hit RETURN. Timeout is in tenths of
# a second.
prompt
timeout=200

# Enable large memory mode.
large-memory

# Specifies the location of the map file. If MAP is
# omitted, a file /boot/map is used.
map=/boot/map

# Specifies the VGA text mode that should be selected when
# booting. The following values are recognized (case is ignored):
#   NORMAL  select normal 80x25 text mode.
#   EXTENDED  select 80x50 text mode. The word EXTENDED can be
#     abbreviated to EXT.
#   ASK  stop and ask for user input (at boot time).
#   <number>  use the corresponding text mode. A list of available modes
#     can be obtained by booting with  vga=ask  and pressing [Enter].
vga=normal

# Defines non-standard parameters for the specified disk.
#disk=/dev/sda
#	bios=0x80

# If you are using removable USB drivers (with mass-storage)
# you will need to tell LILO to not use these devices even
# if defined in /etc/fstab and referenced in /proc/partitions.
# Adjust these lines to your devices:
#
# disk=/dev/sda inaccessible
# disk=/dev/sdb inaccessible

# These images were automagically added. You may need to edit something.

image=/boot/vmlinuz-2.6.31-14-generic
	label="Lin 2.6.31-14"
	initrd=/boot/initrd.img-2.6.31-14-generic
	read-only

image=/boot/vmlinuz-2.6.31-20-generic
	label="Lin 2.6.31-20"
	initrd=/boot/initrd.img-2.6.31-20-generic
	read-only

image=/boot/memtest86+.bin
	label="Memory Test+"
	read-only

# If you have another OS on this machine (say DOS),
# you can boot if by uncommenting the following lines
# (Of course, change /dev/sda1 to wherever your DOS partition is.)
other=/dev/sda6
        label="Fedora 8"

 other=/dev/sda1
   label="Windows XP"

我们将通过创建一个启动软盘来测试我们的配置,因此指定了靠近文件顶部的 boot=/dev/fd0。我们还将提示超时增加到 20 秒(200 个 0.1 秒增量),并添加了第二个 “other” 条目来链式加载到 Fedora 8 分区上的启动加载程序(/dev/sda6)。在一个配置文件中,LILO 只支持一个 root 命令,因此它可以启动 root 分区中的多个映像,但需要链式加载到另一个启动加载程序来启动另一个不同安装中的映像,比如我们的示例中的 Fedora 8 (/dev/sda6) 或 Windows XP (/dev/sda1)。

您可以使用 /sbin/lilo 中的 lilo 命令来编写一个阶段 1 引导记录,并使用通常位于 /etc/lilo.conf 中的配置信息(比如上面的示例)来创建一个映像文件(/boot/map)。我们稍后会提到一些辅助用法。

现在,如果我们使用一个 Linux 文件系统(比如 ext2)来格式化一个软盘,可以运行 lilo 命令(/sbin/lilo)来创建一个可引导软盘。 清单 12 显示了我们的输出。请注意, lilo 命令有 5 个级别,为每个级别指定一个额外的 -v 参数。该示例是使用 lilo -v -v 创建的。

清单 12. 使用 lilo 创建一个可引导软盘
LILO version 22.8, Copyright (C) 1992-1998 Werner Almesberger
Development beyond version 21 Copyright (C) 1999-2006 John Coffman
Released 19-Feb-2007, and compiled at 10:52:38 on Aug 25 2009
Running Linux kernel 2.6.31-14-generic on i686
Ubuntu

raid_setup returns offset = 00000000  ndisk = 0
 BIOS   VolumeID   Device
Reading boot sector from /dev/fd0
pf_hard_disk_scan: ndevs=1
  0800  54085408  /dev/sda
device codes (user assigned pf) = 0
device codes (user assigned) = 0
device codes (BIOS assigned) = 1
device codes (canonical) = 1
mode = 0x03,  columns = 80,  rows = 25,  page = 0
Using BITMAP secondary loader
Calling map_insert_data
Secondary loader: 19 sectors (0x3800 dataend).
Warning: The boot sector and map file are on different disks.
bios_boot = 0x00  bios_map = 0x80  map==boot = 0  map S/N: 54085408
Mapping bitmap file /boot/coffee.bmp
Calling map_insert_file
Compaction removed 592 BIOS calls.
Bitmap: 603 sectors.
BIOS data check was okay on the last boot

Boot image: /boot/vmlinuz-2.6.31-14-generic
Setup length is 26 sectors.
Compaction removed 7452 BIOS calls.
Mapped 7601 sectors.
Mapping RAM disk /boot/initrd.img-2.6.31-14-generic
Compaction removed 14696 BIOS calls.
RAM disk: 14930 sectors.
Added Lin_2.6.31-14 *

Boot image: /boot/vmlinuz-2.6.31-20-generic
Setup length is 26 sectors.
Compaction removed 7468 BIOS calls.
Mapped 7617 sectors.
Mapping RAM disk /boot/initrd.img-2.6.31-20-generic
Compaction removed 14704 BIOS calls.
RAM disk: 14938 sectors.
Added Lin_2.6.31-20

Boot image: /boot/memtest86+.bin
Setup length is 4 sectors.
Compaction removed 243 BIOS calls.
Mapped 254 sectors.
Added Memory_Test+

Boot other: /dev/sda6, loader CHAIN
Pseudo partition start: 43198848
Compaction removed 0 BIOS calls.
Mapped 6 (4+1+1) sectors.
Added Fedora_8

Boot other: /dev/sda1, on /dev/sda, loader CHAIN
Compaction removed 0 BIOS calls.
Mapped 6 (4+1+1) sectors.
Added Windows_XP

 BIOS   VolumeID   Device
  80    54085408    0800
Writing boot sector.
/boot/boot.0200 exists - no boot sector backup copy made.
Map file size: 336896 bytes.
RAID device mask 0x0000
One warning was issued.

我们现在拥有了属于我们自己的可引导 LILO 软盘。如果 LILO 遇到一个错误,您可能会看到一条错误消息,引导扇区将不会被写入。这条错误消息会使您对需要修复的问题有所了解。

如果我们使用刚才创建的软盘并重新启动机器,就会看到一个类似于 图 4 的提示。请注意屏幕顶部的倒数计时器,它从 20 秒向下倒数(200 个 0.1 秒)。如果在 20 秒内没有做出选择,则会自动启动突出显示的选项(第 1 个,本例中的 Lin_2.6.31-14)。

图 4. LILO 启动界面
LILO 启动界面的屏幕截图,显示了第一个重点选择和倒计时器,还有 14 秒。

可以使用方向键上下移动来选择列表。图 5 显示了如何选择较新的 Lin_2.6.31-20 内核,它是第二个选项。请注意,计时器的值不再显示。按 Enter 键启动该内核。

图 5. 使用 LILO 选择另一个启动目标
LILO 启动界面的屏幕截图,显示选中一个不同的启动目标(第二个选项突出显示),没有显示倒数计时器。

测试完启动软盘后,更改 lilo.conf 文件中的 boot=/dev/fd0 条目来安装 MBR 或一个分区引导记录上的 LILO。例如,boot=/dev/sda 将把 LILO 安装到您的第一个硬盘驱动器的主引导记录中。

现在您已经初步了解了 LILO 及其配置文件。您可以从 lilo 命令行覆盖一些配置选项。使用 man liloman lilo.conf,在 lilo 手册页面中找到更多的信息。您还可以在与 lilo 或 lilo-doc 安装包一起安装的 PostScript 用户指南中发现更多的信息。这个用户指南应该安装在您的 documentation 目录中,但具体位置可能因为系统不同而不同。定位这个文件的一种方法是通过 grep 过滤安装包列表。清单 13 展示了如何定位基于 Debian 的 Ubuntu 9.10 系统的用户指南,本文使用的就是这种方法。

清单 13. 使用 dpkg 定位 LILO 用户指南
ian@pinguino:~$ dpkg -L lilo-doc | grep "ps"
/usr/share/doc/lilo-doc/user.ps.gz
/usr/share/doc/lilo-doc/tech.ps.gz

在基于 RPM 的系统(比如 Fedora)上的对应命令为:rpm -ql lilo-doc | grep "ps"

LILO 辅助命令

LILO 有以下辅助命令:

lilo -q
显示映射文件中的信息。
lilo -R
将 lilo 设置为仅在下一次重新启动时自动启动指定系统。这对于自动重新启动远程系统来说是非常方便的。
lilo -I
显示关于一个内核路径的信息。
lilo -u
卸载 lilo 并恢复此前的引导记录。

当 LILO 启动一个 Linux 系统时,您可能想要在启动时提供其他参数。例如,如果您的图形启动没有工作,您可能想要启动到模式 3 或单用户模式中来恢复。如果您选定一个条目然后按 TAB 键,应该能看到一个使用您选择的标签名预先填充的终端窗口,如 图 6 所示。在标签名后面输入的任何文本都将被传递到内核。例如,在我们的示例中,通过向下移动一行并按下 TAB 键来选择最新的 Ubuntu 系统。如果您没有先选择一个名称,那么可能必须输入在标签中指定的全名。您会发现使用比我们的示例更简单的标签可能是一个好主意:键入完整的 Lin_2.6.31.20 会很麻烦。

图 6. 使用 LILO 添加内核参数
终端窗口的屏幕截图显示了如何使用 LILO 将 'single' 添加为内核参数

图 6 中,我们将 “single” 添加到启动参数,这表明我们想启动到单一用户模式来进行某种系统恢复。参阅 恢复 小节,了解关于使用启动参数的更多信息。

还记得吗?在使用 LILO 时,无论何时更新配置文件(/etc/lilo.conf),都必须运行 lilo 命令。如果您添加、移动或删除分区,或者进行其他可能会使生成的启动加载程序失效的更改,也需要运行 lilo 命令。


系统更新

大多数版本会提供一些工具来更新系统。这些工具通常能意识到正在使用的启动加载程序,并将自动更新您的配置文件。如果您构建了自己的自定义内核,或者愿意使用一个带有非标准名称或位置的配置文件,那么可能需要自己更新配置文件。

  • 如果您使用的是 GRUB,那么可以编辑 /boot/grub/grub.conf 文件来进行更改,GRUB 阶段 2 加载程序将在您重新启动时读取这个文件。您通常不需要因为只添加一个新内核而重新安装 GRUB。但是,如果您移动一个分区,或者添加一些驱动器,则有可能需要重新安装 GRUB。别忘了阶段 1 加载程序非常小,它只拥有阶段 2 加载程序的一列块地址。移动分区和已处理更改,阶段 1 将不能再找到阶段 2。我们稍后将会介绍一些恢复策略,并讨论 GRUB 的阶段 1.5 加载程序。
  • 如果您使用的是 GRUB 2,则需要使用 update-grub 命令来重新构建 GRUB 2 配置,如 构建 GRUB 2 配置文件 所述。
  • 如果您使用的是 LILO,那么无论何时更新配置文件、添加一个硬盘驱动器或删除一个分区,都必须运行 lilo 命令。
  • 如果您在不同的分区内运行多个 Linux 系统,请参阅下面的 使用引导分区 小节。

恢复

现在我们来看看您仔细准备的启动设置可能会出错的地方,特别是当您安装并启动多个操作系统时。需要记住的第一点是控制您的初始恐慌冲动。恢复通常很简单。这里介绍的一些策略可以帮助您渡过各种危机。

能够对一台机器进行物理访问的任何人都拥有许多权力。同样,对一个 GRUB 命令行拥有访问权的任何人都能访问您系统上的文件,这对一个运行系统提供的任何所有权或其他安全条款来说并不是一件好事。选择启动加载程序时,一定要牢记这些问题。对于 LILO 和 GRUB 的选择,主要是个人喜好问题。选择最适合您的特殊需求和工作方式的加载程序。

另一个安装会损坏您的 MBR

有时您会安装另一个操作系统,并在无意中覆盖了 MBR。有些系统,比如 DOS 和 Windows,总是安装它们自己的 MBR。从这种情况恢复通常很容易。如果您养成在每次运行 lilo 或重新安装 GRUB 时都创建一张启动软盘的习惯,就可以避免许多烦恼。只需从该软盘启动到您的 Linux 系统并重新运行 lilogrub-install 即可。

如果您没有启动软盘,但是仍然拥有几乎所有 Linux 版本,那么您通常可以在一个恢复模式中启动 Linux 安装媒体。在您这样做时,您的硬盘驱动器上的 root 文件系统要么会在某个奇怪的恢复点挂载,要么完全不被挂载。您可以使用 chroot 命令使这个奇怪的挂载点变为您的根目录(/)。然后运行 lilogrub-install 来创建一张新的启动软盘或重新安装 MBR。 我喜欢创建一张软盘并使用它来启动,这样能够确保我在继续操作并重写 MBR 之前一切正常,但您可能比我更具勇气。在还原模式下启动一张 CD 或 DVD 可能会向您提供一个选项菜单,或者可能只是将您带入拥有 root 权限的单用户模式。如果您试图将我们在 LILO 示例中使用的 Ubuntu 9.10 系统启动到单用户模式,您会看到一个如 图 7 所示的菜单。 突出显示的选项将使您进入一个有网络连接的 root shell。

图 7. Ubuntu 9.10 恢复菜单
终端窗口的屏幕截图显示了使用 GRUB 引导到单用户模式的菜单

这样的一个菜单是恢复介质的一个常用选择。对于我们的还原示例,我们不打算使用 CD,而是将 Ubuntu 9.19 系统启动到之前关于 LILO 的小节中描述的单用户模式。然后,我们逐步执行为另一个系统(这里是 /dev/sda6 上的 Fedora 8 系统)创建一张启动软盘的典型步骤。无论您从一张还原 CD 或相同的系统上的另一个 OS 启动,这些步骤都是类似的,但也有可能已经为您完成了某些步骤(比如,挂载要还原的映像)。

当您最终提供一个 root 提示时,可能想要执行 清单 14 中的全部或部分代码。 对于我们的示例,我们创建一个挂载点(/mnt/sysimage),在这个新的(将来) root 中挂载一些特殊的文件系统,然后 chroot 到已挂载的系统。cat /etc/issue 命令展示 chroot 命令的效果,这使得目标目录成为文件系统的新根目录,至少在我们使用 Ctrl-d 或 exit 命令退出执行了 chroot 的环境之前是这样的。

清单 14 展示了我们此前配置示例中使用的同一环境中的一个示例。将这个示例视为您作为 root 用户登录的一个终端窗口。换句话说,要小心对待即将写入硬盘驱动器的内容。

清单 14. 使用一个还原系统以及 chroot
root@pinguino:~# mkdir /mnt/sysimage
root@pinguino:~# mount /dev/sda6 /mnt/sysimage
root@pinguino:~# cd /mnt/sysimage
root@pinguino:~# mount -t proc none proc/
root@pinguino:~# mount -t sysfs none sys/
root@pinguino:~# mount -o bind /dev dev/
root@pinguino:~# cat /etc/issue
Ubuntu 9.10 \n \l

root@pinguino:~# chroot /mnt/sysimage
root@pinguino:~# 
sh-3.00# chroot /mnt/sysimage
[root@oinguine /]# cat /etc/issue
Fedora release 8 (Werewolf)
Kernel \r on an \m

[root@oinguine /]# grub-install /dev/fd0
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
[root@oinguine /]#

当您配置好您的可引导软盘之后,按下 Ctrl-d 键退出 chroot 环境并重新启动您的系统,别忘了删除可能使用过的任何安装 CD 或恢复媒体。如果您手边碰巧没有安装 CD 或 DVD,那么可以使用诸多在线提供的实时恢复 LINUX CD,或者一些软盘或 USB 磁盘。请参见 参考资料,了解有关的更多细节。

尽管超出了本文的范围,您可能想了解这一点:您还可以使您的 MBR 启动一个 Windows 2000 或 Windows XP 系统,并在一个分区引导记录上安装 LILO 或 GRUB。ntldr 启动程序也可以链式加载其他引导扇区,但是设置可能比较麻烦。您需要将这个引导扇区复制到一个 Windows 分区(通常使用 dd 命令)并修改隐藏的 boot.ini 文件来实现上述操作。

移动一个分区

如果您移动了一个分区并且忘记了启动设置,那么可能会遇到一个意外问题。通常,LILO 和 GRUB 会拒绝加载。LILO 可能会打印一个 “L”,表明阶段 1 被加载,然后停止运行。GRUB 将给出一个错误消息。这里发生的事情是:阶段 1 加载程序(它需要加载一列扇区以达到阶段 2 加载程序)可能从它拥有的地址加载一些扇区,但这些扇区不再拥有阶段 2 签名。如果您使用此前介绍的方法来构建一张启动软盘,别忘了 lilogrub-install 放置到该软盘上的全部内容是一个单一的引导扇区,因此您的启动软盘可能没有什么帮助。正如在之前的示例中,您可能需要引导某种类型的还原环境,然后在您的 MBR 中重新安装您的启动加载程序。

您可能已经注意到,我们的配置示例对分区使用了一些标签和 UUID (Universally Unique IDs)。例如:
kernel /boot/vmlinuz-2.6.26.8-57.fc8 ro root=LABEL=FEDORA8 rhgb quiet

kernel /boot/upgrade/vmlinuz preupgrade repo=hd::/var/cache/yum/preupgrade stage2=\
hd:UUID=8b4c62e7-2022-4288-8995-5eda92cd149b:/boot/upgrade/install.img \
ks=hd:UUID=8b4c62e7-2022-4288-8995-5eda92cd149b:/boot/upgrade/ks.cfg

移动分区时,我经常使用这样的 UUID 来帮助避免问题。您仍然需要更新 GRUB 或 LILO 配置文件并重新运行 lilo,但是不必更新 /etc/fstab。当您在一个系统上创建一个分区映像,并在另一个系统上的一个不同位置上恢复该映像时,这尤为方便。当您从一个驱动器(比如,一个 USB 驱动器)启动时也很方便,该驱动器并不总是附加在同一位置。

使用引导分区

用于恢复(或者可能是避免)的另一种方法是使用一个独立的分区来启动。当您拥有一个测试系统,系统上有几个版本,而且您可能需要频繁重新构建该系统时,这种方法尤其有用。这个引导分区不必非常大,大约 100MB 左右即可。但是这个分区应该不太可能被移动,且不太可能由于添加或删除另一个分区而影响它的分区编号。在一个混合 Windows 和 Linux 环境中,/dev/sda2(或者 /dev/hda2,取决于您的磁盘的标签设置方式)通常是一个不错的引导分区的选择。清单 15 展示了一个小型引导分区(/dev/sda2)中的条目,这个分区实际上由我们一直作为示例使用的系统上的主引导记录加载的。

清单 15. 通过 GRUB 使用一个小型引导分区
# menu.lst - See: grub(8), info grub, update-grub(8)
#            grub-install(8), grub-floppy(8),
#            grub-md5-crypt, /usr/share/doc/grub
#            and /usr/share/doc/grub-doc/.

## default num
# Set the default entry to the entry number NUM. Numbering starts from 0, and
# the entry number 0 is the default if the command is not used.
#
# You can specify 'saved' instead of a number. In this case, the default entry
# is the entry saved with the command 'savedefault'.           
default		0

## timeout sec
# Set a timeout, in SEC seconds, before automatically booting the default entry
# (normally the first entry defined).
timeout		10

## password ['--md5'] passwd
# If used in the first section of a menu file, disable all interactive editing
# control (menu entry editor and command-line)  and entries protected by the
# command 'lock'
# e.g. password topsecret
#      password --md5 $1$gLhU0/$aW78kHK1QfV3P2b2znUoe/
# password topsecret

title           Fedora 8 (sda6) Grub menu
root            (hd0,5)
chainloader     +1
boot

# Ubuntu 9.10 uses GRUB 2, so use kernel to drive GRUB 2 menu.
title           Ubuntu 9.10 (sda7)
root            (hd0,6)
kernel          /boot/grub/core.img

# This is a divider, added to separate the menu items below from the Debian
# ones.
title		Other operating systems:
root

# Windows XP
title		Windows NT/XP
root		(hd0,0)
savedefault
chainloader	+1

当您的 root 分区使用一个您的启动加载程序不支持的文件系统时,也需要一个引导分区。例如,当 root 分区(/)使用 GRUB Legacy 不支持的 LVM 时,将 /boot 分区格式化为 ext2 或 ext3 是非常常见的。

如果您的系统上有多个版本,不要 在它们之间共享 /boot 分区。记得将 LILO 或 GRUB 设置为从稍后将作为 /boot 加载的分区启动。还要记住一点:一个发行版的更新程序通常将会更新该系统的 GRUB 或 LILO 配置。在一个包含多个系统的环境中,您可能想要将一个带有其自己的 /boot 分区的系统作为主系统,并在您的一个系统需要配置文件时手动更新该文件。另一种方法是使每个系统都安装一个启动加载程序到其自己的分区引导记录中,并使您的主系统为这些单独的系统链式加载分区引导记录,从而向您提供一个两阶段菜单过程。

构建一个自包含引导软盘或 CD-ROM

最后,我们将更仔细地检查 GRUB 设置,以及如何构建一个独立的软盘或 CD,它们将使您获得一个 GRUB 提示,无论您的硬盘驱动器出现了什么情况都可以恢复。

如果您对硬盘驱动器布局比较熟悉,正如文章 “学习 Linux 101:硬盘布局” 所讨论的那样,您应该记得所有关于硬盘驱动器柱面的内容。即使您将柱面视作带有现代驱动器的虚构实体,您的文件系统的许多方面仍然涉及到它们。特别是,您会发现,分区使用了几个必不可少的、在柱面边界上对齐的柱面。在一个分区内部,许多文件系统仍然以柱面作为单位来管理空间。在许多 UNIX® 和 Linux 系统上,文件系统的布局存储在一个超级块(superblock)中,它是文件系统的第一个分配单元。对于 ext2 或 ext3 这样的文件系统和相对较大的硬盘驱动器,空间将被分割为几个区域,每个区域的开始部分都有一个超级块副本。如果您不小心使用 fdisk 这类程序混淆了分区边界,这会有助于恢复。

柱面思想的另一个好处是 MBR 后面的磁盘的开头有一些空间。GRUB 通过以下方式来利用这个好处:在这个空间中嵌入一个阶段 1.5 启动加载程序,或者在可能的时候将其放置在一个分区上的类似未使用空间中。这个阶段 1.5 加载程序理解包含阶段 2 的分区上的文件系统,因此能够在一定程度上更好地保护系统免受移动文件的影响。

这样的确不错,但它如何关联到一张可引导软盘呢?的确,软盘没有太多空间,也没有多少柱面概念,因此,如果您想要从一张软盘同时启动 GRUB 的阶段 1 和阶段 2,则必须安装阶段 1,并立即将阶段 2 复制到引导扇区后的扇区。清单 16 展示了这样一个示例。使用一张空白软盘,因为这个过程可能损坏数据。应该复制您的 GRUB 版本中的文件,而来自 /boot/grub 目录的文件,因为 /boot/grub/stage2 已经被修改为使用您的硬盘驱动器分区。您可以在 /usr/share/grub 目录的一个子目录中找到原始的 stage1 和 stage2 文件。在我们的示例中,它们位于 /usr/share/grub/i386-redhat 中。

清单 16. 创建一个 GRUB 启动软盘
[root@pinguino ~]# ls /usr/share/grub/
i386-redhat
[root@pinguino ~]# cd /usr/share/grub/i386-redhat/
[root@pinguino i386-redhat]# ls -l st*
-rw-r--r-- 1 root root    512 2008-05-28 12:05 stage1
-rw-r--r-- 1 root root 109212 2008-05-28 12:05 stage2
-rw-r--r-- 1 root root 109212 2008-05-28 12:05 stage2_eltorito
[root@pinguino i386-redhat]# dd if=stage1 of=/dev/fd0 bs=512 count=1
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.29007 s, 1.8 kB/s
[root@pinguino i386-redhat]# dd if=stage2 of=/dev/fd0 bs=512 seek=1
213+1 records in
213+1 records out
109212 bytes (109 kB) copied, 7.4094 s, 14.7 kB/s


[root@lyrebird root]# ls /usr/share/grub
i386-redhat
[root@lyrebird root]# cd /usr/share/grub/i386-redhat
[root@lyrebird i386-redhat]# ls -l st*
-rw-r--r--    1 root     root          512 Aug  3  2004 stage1
-rw-r--r--    1 root     root       104092 Aug  3  2004 stage2
[root@lyrebird i386-redhat]# dd if=stage1 of=/dev/fd0 bs=512 count=1
1+0 records in
1+0 records out
[root@lyrebird i386-redhat]# dd if=stage2 of=/dev/fd0 bs=512 seek=1

203+1 records in
203+1 records out

如果您在执行这个操作之前使用 MS-DOS 格式化软盘启动,而且现在想要挂载这张软盘,那么挂载命令将产生一个错误。在该软盘引导扇区(seek=1)损坏软盘上的文件系统后复制 stage2。

尽管创建一个可引导的 GRUB CD 的方法基本相似,但需要在硬盘驱动器上准备这个 CD 映像。您还需要一个临时目录,比如 grubcd,并包含子目录 boot 和 boot/grub。然后,需要将 stage2_eltorito 文件从 GRUB 版本复制到您刚刚创建的 grub 子目录中。然后使用 genisoimage 创建一个可引导的 .iso 映像文件,您可以使用自己喜欢的刻录工具将该文件刻录到 CD 中。清单 17 展示了如何将这个 CD 映像创建为 grubcd.iso。

清单 17. 创建一个 GRUB 可引导 CD 映像
[ian@pinguino ~]$ mkdir -p grubcd/boot/grub
[ian@pinguino ~]$ cp /usr/share/grub/i386-redhat/stage2_eltorito grubcd/boot/grub
[ian@pinguino ~]$ 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 0
233 extents written (0 MB)

您可以在任意一台 PC 机上启动 CD 或软盘;没必要一定在 Linux 系统上执行此操作。如果立刻启动该软盘,那么从软盘加载阶段 2 时会有一个延迟。类似地,如果启动 CD,则会从 CD 加载 GURB shell。不管从哪里启动,都会得到一个 GRUB 启动提示。可以按下 Tab 键查看可用命令的列表。尝试使用 help commandname 命令获取关于 commandname 命令的帮助文件。清单 18 展示了 GRUB 命令行。

清单 18. GRUB 命令行
    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> 
 Possible commands are: blocklist boot cat chainloader clear cmp color configfile 
 debug device displayapm displaymem dump embed find fstest geometry halt help
 hide impsprobe initrd install ioprobe kernel lock makeactive map md5crypt 
 module modulenounzip pager partnew parttype password pause quit read reboot 
 root rootnoverify savedefault serial setkey setup terminal terminfo testload testvbe
 unhide uppermem vbeprobe

grub> 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. Note that the items mentioned in `root' which derived
    from attempting the mount will NOT work correctly.

grub> find /boot/grub/grub.conf
 (hd0,1)
 (hd0,5)

grub>

在该示例中,我们发现第一个硬盘驱动器的两个不同分区上有一些 GRUB 配置文件。可以使用 configfile 命令从其中一个配置文件加载 GRUB 菜单。例如:configfile (hd0,1)/boot/grub/grub.conf

这将加载该配置文件的菜单,我们可以从该点启动系统。您可以在 GRUB 手册中深入了解这些 grub 命令。在一个 Linux 终端窗口中尝试输入 info grub 命令来打开该手册。

下面是我们结束 GRUB 介绍之前的最后一点说明。前面已经介绍过,阶段 2 GRUB 文件会损坏软盘上的文件系统。如果您想要创建一个加载 GRUB 文件(包括一个配置文件)的可引导 GRUB 恢复软盘,那么可以通过以下步骤来完成:

  1. 使用 mkdosfs 命令在软盘上创建一个 DOS FAT 文件系统,并使用 -R 选项为阶段 2 文件保留足够的扇区。
  2. 挂载软盘
  3. 在软盘上创建一个 /boot/grub 目录。
  4. 将 GRUB stage1、stage2 和 grub.conf 文件复制到软盘上的 boot/grub 目录。如果愿意的话,还可以复制您的 splash 映像文件。
  5. 编辑软盘上的 grub.conf 文件,以便引用软盘上的 splash 文件。
  6. 卸载该软盘
  7. 使用 grub 命令 shell 中的 GRUB root 和 setup 命令在软盘上设置 GRUB。

清单 19 展示了这个过程。

清单 19. 在包含一个文件系统的软盘上安装 GRUB
[root@pinguino ~]# mkdosfs -R 220 /dev/fd0
mkdosfs 2.11 (12 Mar 2005)
[root@pinguino ~]# mkdir /mnt/floppy
[root@pinguino ~]# mount /dev/fd0 /mnt/floppy
[root@pinguino ~]# mkdir -p /mnt/floppy/boot/grub
[root@pinguino ~]# cp /boot/grub/stage1 /mnt/floppy/boot/grub
[root@pinguino ~]# cp /boot/grub/stage2 /mnt/floppy/boot/grub
[root@pinguino ~]# cp /boot/grub/splash* /mnt/floppy/boot/grub
[root@pinguino ~]# cp /boot/grub/grub.conf /mnt/floppy/boot/grub
[root@pinguino ~]# umount /dev/fd0
[root@pinguino ~]# grub
Probing devices to guess BIOS drives. This may 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> root (fd0)
 Filesystem type is fat, using whole disk

grub> setup (fd0)
 Checking if "/boot/grub/stage1" exists... yes
 Checking if "/boot/grub/stage2" exists... yes
 Checking if "/boot/grub/fat_stage1_5" exists... no
 Running "install /boot/grub/stage1 (fd0) /boot/grub/stage2 p /boot/grub/grub.c
onf "... succeeded
Done.

这个示例也展示了这样一个事实:可以在一个 Linux shell 中运行 grub 命令。这是了解 GRUB 的一个好方法,没有必要总是重启计算机。您需要 root 权限才能运行 grub 命令,而且您可以完成 GRUB 可以完成的大部分任务,除了重新启动系统。

GRUB 2 的恢复介质

GRUB 2 带有一个 grub-mkrescue 命令,可帮助您创建一个恢复软盘或 CD 映像。最新版 grub-mkrescue 使用 xorriso 安装包而不是 mkisofs 安装包来创建 ISO 映像,如果第一次尝试失败,而且出现这样一条消息:“xorriso: command not found(xorriso: 找不到命令)”,那么您可能需要安装相应的安装包。清单 20 展示了如何在文件 rescue.iso 中创建一个 GRUB 2 恢复映像。不需要使用 root 权限创建还原 ISO。我们在这里使用 root 权限是为了向您展示如何创建一个可引导 USB 闪存驱动器,该驱动需要 root 权限。

清单 20. 创建一个 GRUB2 还原映像
[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)。如果您喜欢的话,也可以将它复制到 U 盘,然后从 U 盘启动,假设您的 BIOS 支持从这类设备启动。清单 21 显示如何使用 dd 命令将 ISO 映像复制到 U 盘 /dev/sdc。

警告:务必确保将该映像复制到正确设备。复制到错误设备可能损坏大量数据。

清单 21. 将 GRUB2 恢复映像写入 USB 闪存驱动器
[root@echidna ~]# dd if=rescue.iso of=/dev/sdc
4376+0 records in
4376+0 records out
2240512 bytes (2.2 MB) copied, 0.625654 s, 3.6 MB/s

现在,您有了一个可引导的 USB 闪存驱动器,它将引导到一个 GRUB 2 提示。可在 GRUB 手册页详细了解 GRUB 2 命令。可以尝试在 Linux 终端窗口输入 info grub2 命令来打开手册页。


结束语

现在,您已经学习了传统 Linux 系统的主要启动加载程序,包括如何从错误和启动问题中恢复。


下载

描述名字大小
本文中使用的配置文件l-lpic1-v3-102-2-samples.zip8KB

参考资料

学习

获得产品和技术

  • 下载 系统还原光盘,这是能帮助您在系统崩溃后恢复系统的一种在线工具。
  • 以最适合您的方式 评估 IBM 产品:下载产品试用版,在线试用产品,在云环境下试用产品,或在 SOA Sandbox 中花费几个小时来学习如何高效实现面向服务的架构。

讨论

  • 加入 developerWorks 社区。探索由开发人员推动的博客、论坛、组和维基,并与其他 developerWorks 用户进行交流。

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


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