RHCSA&RHCE(RHCE7)学习深入--GNU GRUB2

 

概述

GRUB--GRand Unified Bootloader

bootloader是计算机启动时运行的第一个程序,它的主要任务是加载并转交控制权给操作系统内核(比如Linux或GNU Mach),内核再依次初始化操作系统的其余部分。

GNU GRUB是一个非常强大的boot loader,它可以加载各种各样的免费操作系统,也可以加载带有chain-loading的专有操作系统。GRUB主要解决引导个人计算机的问题;程序和本手册都紧密地绑定到该计算机平台,移植到其他平台可能会在将来解决。

GRUB的一个重要特性是灵活性;GRUB识别文件系统和内核执行格式,因此可以以自己喜欢的方式加载任意操作系统,而无需记录内核在磁盘上的物理位置。因此,只需指定内核的文件名以及内核所在的驱动器和分区,就可以加载内核。

使用GRUB启动时,可以使用命令行接口或菜单界面。使用命令行接口,手动输入内核所在的驱动器和文件名。在菜单界面中,只需使用箭头键选择一个OS。菜单基于预先准备的配置文件。在菜单中,可以切换到命令行模式,反之亦然。甚至可以在使用之前编辑菜单项。

 

GRUB的历史

GRUB起源于1995年,当时Erich Boleyn正试图用犹他大学的Mach 4微内核(现在称为GNU Mach)启动GNU Hurd。Erich和BrianFord设计了多重引导(multiboot)规范,他们决定不添加大量互不兼容的PC引导方法。

然后,Erich开始修改FreeBSD引导加载程序,以便它能够理解多重引导(multiboot)。他很快意识到,从零开始编写自己的引导加载程序要比继续在FreeBSD引导加载程序上修改要容易得多,于是GRUB诞生了。

扫描二维码关注公众号,回复: 4986383 查看本文章

Erich在GRUB中增加了许多特性,但其他优先事项使他无法跟上GRUB迅速扩展的用户群的需求。1999年,Gordon Matzigkeit和Yoshinori K.Okuji采用GRUB作为官方GNU软件包,并通过匿名CVS提供最新消息来源,开启了GRUB的开发。

在接下来的几年里,GRUB为了满足许多需求被不断扩展,但很快就发现,它的设计限制了它的扩展,在不破坏现有特性的情况下,很难做任何进一步的改变。2002年前后,Yoshinori K.Okuji开始研究PUPA(GNU GRUB的初步通用编程体系结构),目的是重写GRUB的核心,使其更干净、更安全、更健壮和更强大。最终改名为GRUB 2,最初版本的GRUB被重命名为GRUB Legacy。继续对GRUB Legacy进行少量的维护,但上一次发布(0.97)是在2005年,在撰写本文档时,似乎不太可能有另一个版本。

到2007年左右,GNU/Linux发行版开始使用GRUB 2,到2009年底,多个主要发行版默认都在安装GRUB 2。

 

与上一个版本的不同

GRUB 2是对GRUB的重写,尽管它与以前的版本(现在称为GRUB Legacy)有许多共同的特性,但GRUB Legacy的用户可能需要一些指导才能找到这个新版本的特性。

  1. 新的配置文件名称(‘grub.cfg’而不是‘menu.lst’或‘grub.conf’),新的语法和一些新的命令,配置不能直接复制。
  2. “grub.cfg”通常由grub-mkconfig自动生成,这使得处理版本化的内核升级更加容易。
  3. GRUB设备名称中的分区号现在从1开始,而不是0。
  4. 配置文件现在是用更接近完整脚本语言的东西编写的:变量、条件和循环是可用的。
  5. 通过重新引导,可以使用GRUB中的save_env和load_env命令以及grub-editenv工具使用少量的持久配置。这并非在所有配置中都可用。
  6. GRUB 2有更可靠的方法在多磁盘系统上找到自己的文件和目标内核的文件,并有命令使用文件系统标签或通用唯一标识符(UUID)查找设备。
  7. 除了GRUB Legacy支持的PC BIOS系统之外,GRUB 2还可以用于其他几种类型的系统:支持PC EFI、PC coreboot、PowerPC、SPARC和MIPS LeMote Yeeloong。
  8. 支持更多的文件系统,包括但不限于ext4、HFS和NTFS。
  9. GRUB 2可以直接从LVM和RAID设备读取文件。
  10. 图形终端和图形菜单系统可用。
  11. GRUB 2的界面可以翻译成其他语言,包括菜单项名称。
  12. 组成GRUB的image文件已被重新组织;第1阶段、第1.5阶段和第2阶段已不复存在。
  13. GRUB 2将许多功能放在动态加载的模块中,使核心image更小,并允许以更灵活的方式构建核心image。

 

GRUB特性

GRUB的主要特性是它符合多重引导(multiboot)规范,

按重要程度排列的其他特性如下:

  1. 对于最终用户来说,基本功能必须是明确的。
  2. 支持内核专家和设计人员的丰富功能。
  3. 引导FreeBSD、NetBSD、OpenBSD和Linux的向后兼容性。专有内核(如DOS、WindowsNT和OS/2)通过chain-loading功能得到支持。

除了特定的兼容性模式(chain-loading和linux piggyback格式)外,所有内核都将在与Multiboot规范中相同的状态下启动。目前只有装载在1 MB或以上的内核才能得到支持。任何在边界以下加载的尝试都只会导致立即失败和报告错误消息。

除了上面的要求之外,GRUB还有以下特性(请注意,多重引导(multiboot)规范并不需要GRUB支持的所有特性):

  1. 识别多种可执行格式

支持许多a.out变体加上ELF。还加载了符号表。

  1. 支持非多引导内核

支持许多缺乏多重引导兼容性的免费32位内核(主要是FreeBSD、NetBSD 2、OpenBSD和Linux)。还支持其他引导加载程序的Chain-loading。

  1. 加载多个模块

完全支持加载多个模块的多重引导功能。

  1. 加载配置文件

支持带有预置引导命令的文本配置文件,还可以动态加载一个配置文件,并将预设的配置文件嵌入到GRUB image文件中。命令列表是命令行中支持的命令的超集。

  1. 提供菜单界面

一个列出预置引导命令的菜单接口(带有可编程超时)是可用的。引导条目的数量没有固定的限制,当前的实现有数百个的空间。

  1. 具有灵活的命令行接口

一个相当灵活的命令行界面,可从菜单中访问,可用于编辑任何预置命令,或从头开始编写新的引导命令集。如果没有配置文件,GRUB将进入到命令行中。

命令列表是配置文件支持的命令的子集。编辑命令与bash命令行非常相似,使用TAB-自动补全命令、设备、分区和文件。

  1. 支持多种文件系统类型

支持多个文件系统类型,外加一个有用的显式区块列表表示法。当前支持的文件系统类型是Amiga Fast (AFFS), AtheOS fs, BeFS, BtrFS (including raid0, raid1, raid10, gzip and lzo),cpio (little-and big-endian bin, odc and newc variants), Linux ext2/ext3/ext4,DOS FAT12/FAT16/FAT32, exFAT, HFS, HFS+, ISO9660 (including Joliet,Rock-ridge and multi-chunk files), JFS, Minix fs (versions 1, 2 and 3), nilfs2,NTFS (including compression), ReiserFS, ROMFS, Amiga Smart FileSystem(SFS), Squash4, tar, UDF, BSD UFS/UFS2, XFS, and ZFS (including lzjb,gzip, zle, mirror, stripe, raidz1/2/3 and encryption in AES-CCM and AESGCM)

  1. 支持自动解压缩

可以解压缩gzip或xz压缩的文件,该功能对用户来说是自动的和透明的(也就是说,所有功能都对指定文件的未压缩内容进行操作)。这大大减少了文件大小和加载时间,对于floppies来说,这是一个特别大的好处。这样,某些内核模块可以以压缩状态加载,不必对模块进行解压缩。

  1. 访问任何已安装设备上的数据

支持从BIOS识别的任何软盘或硬盘读取数据,而不依赖根设备的设置。

  1. Be independent of drive geometry translations

Unlike many other boot loaders, GRUB makes the particular drive translation irrelevant. A drive installed and running with one translation may be converted to another translation without any adverse effects or changes in GRUB’s configuration.

  1. 检测所有已安装的RAM

GRUB通常可以在与PC兼容的计算机上找到所有已安装的RAM,它使用一种高级的BIOS查询技术来查找所有内存区域。并不是所有的内核都使用这些信息,但是GRUB提供给那些需要的人。

  1. 支持逻辑块地址模式

在传统的磁盘调用(称为chs模式)中,存在一个几何转换问题,BIOS不能访问大于1024个柱面,因此访问空间限制在至少508 MB,最大可访问空间为8GB。GRUB不能解决这个问题,因为所有机器没有使用标准的接口。所以,一些新的机器就有新的接口,逻辑块地址(LBA)模式。GRUB自动检测,如果LBA模式可用则使用它。在LBA模式下,GRUB可以访问整个磁盘。

  1. 支持网络启动

GRUB是基于磁盘的引导加载器也支持网络,可以使用TFTP协议从网络加载OS映像。

  1. 支持远程终端

为了支持没有控制台的计算机,GRUB提供远程终端支持,以便您可以从远程主机控制GRUB。目前只实现了串行终端的支持。

 

命名约定

GRUB中使用的设备语法与在操作系统中可能看到的略有不同。

(fd0)

首先,GRUB要求将设备名称用‘(’和‘)括起来。“fd”表示它是软盘。数字‘0’是驱动器号,从零开始。这个表达式表示GRUB将使用整个软盘。

(hd0,msdos2)

在这里,“hd”表示是硬盘驱动器。第一个‘0’表示驱动器号,即第一个硬盘,字符串‘msdos’表示分区模式,而第二个‘2’表示分区号(或BSD术语中的PC片号)。分区号从1开始不是从0(以前版本的GRUB是从0开始)。这个表达式表示第一个硬盘驱动器的第二个分区。GRUB使用磁盘的一个分区,而不是整个磁盘。

(hd0,msdos5)

这指定了第一个硬盘驱动器的第一个扩展分区。扩展分区的分区号是从“5”开始,而不管硬盘上主分区的实际数量。

(hd1,msdos1,bsd1)

这表示第二个硬盘的第一个PC片号上的BSD‘a’分区。

实际上,使用GRUB访问磁盘或分区时,需要在命令中指定设备,比如‘set root=(fd0)’或‘parttools(hd0,msdos3) hidden-’。

为了帮助找到所需分区的编号,GRUB命令行具有参数补全功能。

例如,你只需要输入

set root=(

再输入一个TAB,GRUB将显示驱动器、分区或文件名的列表。因此,即使对语法知之甚少,也能很容易确定目标分区的名称。

注意,GRUB并不区分IDE和SCSI的类型,它的驱动器号都从零开始。通常,IDE驱动器号都小于SCSI驱动器号,但如果通过在BIOS中交换IDE和SCSI驱动器来更改引导序列,则情况并非如此。

那怎样指定一个文件呢?

(hd0,msdos1)/vmlinuz

这指定了名为“vmlinuz”的文件,位于第一个硬盘驱动器的第一个分区上。注意,参数补全也适用于文件名。

 

安装

要使用GRUB作为引导加载器,首先需要在UNIX的操作系统下安装GRUB系统和实用程序,可以通过源码或操作系统的安装包来安装。

完成软件安装后,需要在UNIX的操作系统上使用grub-install工具在驱动器(软盘或硬盘)上安装引导加载器。

GRUB附带引导image,一般放在目录‘/usr/lib/grub/<cpu>-<Platform>’(用于基于BIOS的机器在‘/usr/lib/grub/i386-PC’)。最初放置GRUB image的目录(通常是‘/usr/lib/grub/<cpu>-<Platform>’)将被称为image目录,引导加载程序需要查找它们的目录(通常为‘/boot’)将称为引导目录。

使用grub-install安装GRUB

在UNIX的操作系统下安装GRUB,以超级用户(root)的身份运行grub-install。

只需要为程序指定一个参数,即在哪里安装引导加载程序。参数必须是一个设备文件(比如‘/dev/hda’)。例如,在Linux下,将GRUB安装到第一个IDE磁盘的MBR中:

# grub-install /dev/sda

同样,在GNU/Hurd下,这也有同样的效果:

# grub-install /dev/hd0

但上述所有示例都假设GRUB将image放在‘/boot’目录下。如果希望GRUB将image放在‘/boot’以外的目录下,则需要指定‘--boot-directory’选项。一般的用法是使用文件系统创建GRUB引导软盘。以下是一个例子:

# mke2fs /dev/fd0
# mount -t ext2 /dev/fd0 /mnt
# mkdir /mnt/boot
# grub-install --boot-directory=/mnt/boot /dev/fd0
# umount /mnt

有些BIOSes错误地将USB驱动器的第一个分区识别为软盘,而不是将USB驱动器识别为硬盘(称之为“USB-FDD”引导)。在这种情况下,需要像这样安装:

# losetup /dev/loop0 /dev/sdb1

# mount /dev/loop0 /mnt/usb

# grub-install --boot-directory=/mnt/usb/bugbios --force --allow-floppy /dev/loop0

此安装与标准安装没有冲突,只要它们位于单独的目录中。

grub-install实际上只是一个shell脚本,真正的任务是由其他工具完成,比如grub-mkimage。因此,可以直接运行这些命令来安装GRUB,而无需使用grub-install。但是,建议不要这样做,除非非常熟悉GRUB的内部结构。在运行中的操作系统上安装引导加载程序可能非常危险。

在用于固定磁盘安装的EFI系统上,必须挂载EFI系统分区。如果在‘/boot/efi’上挂载它,则不需要任何特殊参数:

# grub-install

否则,需要指定安装EFI系统分区的位置:

# grub-install --efi-directory=/mnt/efi

对于可移动设备安装,必须使用“--removable”参数并同时指定“--boot-directory”和“--efi-directory”:

#grub-install --efi-directory=/mnt/usb --boot-directory=/mnt/usb/boot --removable

 

制作一个可启动的GRUB光盘

GRUB支持El Torito规范中的无仿真模式。可以让GRUB使用整个CD-ROM,而不必制作软盘或硬盘映像文件,这可能会导致兼容性问题。

从CD-ROM启动,GRUB使用一个名为‘cdboot.img’的特殊image,它与‘core.img’连接。为此使用的“core.img”要使用“iso9660”和“biosdisk”模块。可引导光盘通常还需要包括一个配置文件‘grub.cfg’和其他一些GRUB模块。

要制作一个简单的通用GRUB救援CD,可以使用grub-mkimage程序。

$ grub-mkrescue -o grub.iso

通常需要在image中包含其他文件。为此,首先为可引导image创建一个顶级目录,例如,“iso”:

$ mkdir iso
创建GRUB目录:

$ mkdir -p iso/boot/grub

如果需要,将配置文件“grub.cfg”放在“iso/boot/grub”下,并将光盘的文件和目录复制到目录“iso/”中。

最后,制作image

$ grub-mkrescue -o grub.iso iso

会产生一个名为“grub.iso”的文件,该文件可以刻录到CD(或DVD)中,也可以写入USB存储设备。

在“grub.cfg”配置文件中设置了根设备,因此您可以引用CD上的文件,而无需使用显式的设备名称。这使得在光驱和USB大容量存储设备上产生救援image变得更加容易。

 

BIOS驱动器与OS设备之间的映射

如果存在device map文件,则GRUB工具(grub-probe等)读取它可以将BIOS驱动器映射到OS设备。该文件由如下行组成:

(device) file

device是GRUB语法中指定的驱动器,而文件是OS文件,通常是设备文件。

过去,使用设备映射文件是因为GRUB设备名称必须在配置文件中使用,并且它们是从BIOS驱动器号派生出来的。BIOS驱动器和OS设备之间的映射并不总是正确的:例如,如果在BIOS中在IDE和SCSI之间交换引导序列,GRUB将得到错误的顺序。

不过,即使是OS设备名称也不总是稳定的。新版本的Linux内核可能会根据不同的引导顺序检测驱动器,前缀(‘/dev/hd*’和‘/dev/sd*’)可能会根据使用的驱动子系统而改变。因此,设备映射文件需要在某些系统上进行频繁编辑。

GRUB在生成“grub.cfg”时使用UUID或文件系统标签来避免了这个问题,建议编写自定义菜单项也这样做。

If the device map file does not exist, then the GRUB utilities will assume a temporary device map on the fly. This is often good enough, particularly in the common case of single-disk systems.

However, the device map file is not entirely obsolete yet, and it is used for overriding when current environment is different from the one on boot. Most common case is if you use a partition or logical volume as a disk for virtual machine.

如果需要,可以在文件中添加任何注释,因为GRUB实用程序假定,如果第一个字符是‘#’,这一行就是注释。

 

BIOS安装

 

MBR

传统的在PC BIOS平台上使用的分区表格式称为Master Boot Record (MBR)格式;允许最多四个主分区和附加逻辑分区。对于这种分区表格式,有两种方法可以安装GRUB:可以嵌入到MBR和第一个分区之间的区域(用不同的名称调用,例如“boot track”、“MBR gap”或“embedding area”,通常至少是31 Kib);或者,核心image可以安装在文件系统中,组成它的块列表可以存储在该分区的第一个扇区中。

每一个都有不同的问题。没有办法在嵌入区域内保留完全安全的空间,而且已知一些专有软件会使用它存放license而用户难以绕过;系统有时在第一个分区之前不留出足够的空间。另一方面,将GRUB安装到文件系统意味着GRUB易受文件系统特性(如尾填充)移动其块的影响,甚至是因为积极的fsck,所以这种方法是相当脆弱的;这种方法只能在‘/boot’文件系统位于与BIOS引导的磁盘相同的情况下使用,这样GRUB就不必依赖于BIOS驱动器号。

GRUB开发团队通常建议在第一个分区之前嵌入GRUB,除非有特殊的需求。必须确保从磁盘开始到第一个分区开始的地方至少有31Kib(63个扇区);在现代磁盘上,在更大的边界上划分分区通常具有性能优势,因此第一个分区可能从磁盘开始的1 MIB。

 

GPT

一些较新的系统使用GUID Partition Table (GPT)格式。它是Extensible Firmware Interface (EFI)的一部分,但如果系统软件支持BIOS平台的话,也可以在BIOS平台上使用;例如,可以在此配置中使用GRUB和GNU/Linux。有了这种格式,就可以为GRUB保留一个完整的分区,称为BIOS Boot Partition。可以将GRUB嵌入到该分区中,而不必冒被其他软件覆盖的风险,也不会被包含在可能移动其块的文件系统中。

在GPT系统上创建BIOS Boot Partition时,应确保其大小至少为31 Kib (GPT格式的磁盘通常并不特别小,因此建议使其大于最小值,如1 MIB,以便有足够的增长空间)。还必须确保它具有正确的分区类型。使用GNU Parted,可以使用如下命令来设置它:

# parted /dev/disk set partition-number bios_grub on

如果使用gdisk,则将分区类型设置为“0xEF02”。对于直接需要设置GUID的分区程序,应该是‘21686148-6449-6e6f-744 e6564454649’。

注意:要非常小心选择分区!当GRUB在安装过程中发现BIOS Boot Partition时,它将自动覆盖其中的一部分。确保分区不包含任何其他数据。

 

引导

 

如何引导操作系统

GRUB有两种不同的引导方法。其中一个是直接加载一个操作系统,另一个是chain-load另一个引导加载程序,然后加载一个操作系统。前者更可取,因为不需要安装或维护其他引导加载程序,而且GRUB具有足够的灵活性,可以从任意磁盘/分区加载操作系统。但是,后者有时是必需的,因为GRUB本身并不支持所有现有的操作系统。

 

如何使用GRUB直接引导操作系统

Multiboot是GRUB支持的格式,还支持Linux、FreeBSD、NetBSD和OpenBSD。如果想引导其他操作系统,则必须将它们chain-load。

 

Chain-loading一个操作系统

操作系统不支持Multiboot且在GRUB中也不支持 (对Linux、FreeBSD、NetBSD和OpenBSD的支持)必须是Chian-load,这需要加载另一个引导加载程序并以实际模式跳转到其中。

使用chainloader命令来配置。通常还需要加载一些GRUB模块并配置适当的根设备。对于第一个硬盘的第一个分区上的Windows系统,可以这样配置:

menuentry "Windows" {
insmod chain
insmod ntfs
set root=(hd0,1)
chainloader +1

}

在有多个硬盘的系统上,可能需要额外的解决方法。Chain-loading只支持PC BIOS和EFI平台。

 

loopback引导

GRUB可以读取存储在任何可访问存储中的image(无论是cd还是hdd)。操作系统本身能够找到它自己的根,通常是在真正的根被发现之前运行一个用户空间程序,是通过GRUB加载一个特别制作的小映像并将其作为ramdisk传递到内核来实现的。通过命令kfreebsd_module, knetbsd_module_elf, kopenbsd_ramdisk, initrd,initrd16,multiboot_module,multiboot2_module 或 xnu_ramdisk (取决于加载程序)来实现的。

 

引导GNU/Linux

从GRUB引导GNU/Linux相对容易一些,因为它在某种程度上类似于启动符合Multiboot的操作系统。

1.将GRUB的根设备与GNU/Linux配置在同一个驱动器。命令search --set=root --file/vmlinuz或类似命令可以帮助您

2.使用linux命令加载内核

grub> linux /vmlinuz root=/dev/sda1

如果需要指定一些内核参数,只需将它们附加到命令的后面即可。例如,若要将“ACPI”设置为“OFF”,请执行以下操作:

grub> linux /vmlinuz root=/dev/sda1 acpi=off

对于Linux,GRUB使用32位协议。有些BIOS服务,如APM或EDD,在此协议中不可用。这时需要使用linux16。

grub> linux16 /vmlinuz root=/dev/sda1 acpi=off

3.如果使用initrd,则在linux命令之后执行命令initrd。

grub> initrd /initrd

如果使用linux16,则需要使用initrd16:

grub> initrd16 /initrd

4.最后运行boot命令。

 

制作配置文件

GRUB的配置文件是“grub.cfg”,一般在“/boot/grub”目录下,这个文件非常灵活,但是大多数用户不需要手工编写整个配置文件。

简单配置处理

程序GRUB-mkconfig生成“grub.cfg”文件,适用于大多数情况。它适合在升级发行版时使用,并且会发现可用的内核并尝试为它们生成菜单项。

grub-mkconfig有一些限制。可以通过编辑‘/etc/grub.d/40_custom’或创建‘/boot/grub/custom.cfg’,在列表末尾添加额外的自定义菜单项,更改菜单项的顺序或更改其标题需要对‘/etc/grub.d/’中的shell脚本进行复杂的配置。

文件/etc/default/grub控制grub-mkconfig的操作,它是类似shell脚本的,因此必须是有效的POSIX shell输入;通常,它是‘key=value’行的序列,但是如果值包含空格或其他特殊字符,则必须用引号。例如:

GRUB_TERMINAL_INPUT="console serial"

 

/etc/default/grub中可用的key:

GRUB_DEFAULT

默认的菜单项,可以使一个数字,它标识生成菜单中从零开始的第N个,或是菜单项的标题,或是指定为字符串‘saved’,还有使用id是一个很好的方法,例如:

menuentry ’Example GNU/Linux ’ --class gnu-linux --id example-gnu-linux {
...
}
配置默认为:

GRUB_DEFAULT=example-gnu-linux

以前,记录了使用菜单标题的方式。虽然这仍然有效,但不建议这样做,因为标题通常包含不稳定的设备名称,并且可能会被转换。

如果将其设置为“saved”,则默认菜单项将是“GRUB_SAVEDEFAULT”或grub-set-default配置,这依赖于环境,不是所有情况下都可用的。

默认值为“0”。

GRUB_SAVEDEFAULT

如果设置为“true”,当菜单被选择时,将其保存为新的默认菜单,下次运行GRUB时使用这个默认菜单。只有在‘GRUB_DEFAULT=saved’时才有用;它是一个单独的选项,因为‘GRUB_DEFAULT=saved’与grub-set-default一起使用。默认这个选项没有配置。

GRUB_TIMEOUT

在菜单显示几秒钟后启动默认菜单,除非按下键。默认值是5,配置为0表示立即引导不显示菜单,或者配置为“-1”表示一直等待。

如果“GRUB_TIMEOUT_STYLE”设置为“countdown”或“hidden”,则在显示菜单之前将超时计数。

GRUB_TIMEOUT_STYLE

如果未设置或设置为“menu”,则GRUB将显示菜单,等待“GRUB_TIMOUT”设置的超时过期,然后启动默认菜单。按下键会中断超时。

如果设置为“countdown”或“hidden”,则在显示菜单之前,GRUB将等待“GRUB_TIMOUT”设置的超时过期。

如果ESC在此期间按下,它将显示菜单并等待输入。如果按下与菜单项关联的热键,它将立即启动相关的菜单项。如果超时在任何一种发生之前过期,它将启动默认菜单。在“countdown”的情况下,它将显示出剩余时间的指示。

GRUB_DISTRIBUTOR

由GRUB的分销商设置为他们的识别名称。这是用来生成更多信息的菜单标题。

GRUB_CMDLINE_LINUX

添加到菜单项命令行中的Linux内核的参数。

GRUB_CMDLINE_LINUX_DEFAULT

除非‘GRUB_DIAD_Recovery’被设置为‘true’,否则将为每个Linux内核生成两个菜单项:一个默认菜单和一个恢复模式菜单。此选项列出命令行参数,仅在“GRUB_CMDLINE_LINUX”中列出的命令行参数之后添加到默认菜单项中。

GRUB_DISABLE_LINUX_UUID

通常,grub-mkconfig将生成菜单项使用通用唯一标识符(UUID)来标识Linux内核的根文件系统,使用‘root=UUID=.’参数这通常更可靠,但在某些情况下可能不合适。若要禁用UUID的使用,请将此选项设置为“true”。

GRUB_DISABLE_RECOVERY

如果此选项设置为“true”,则禁用生成恢复模式菜单项。

GRUB_GFXMODE

设置在“gfxterm”图形终端上使用的分辨率。默认值是“auto”,它尝试选择一个优选的分辨率。

GRUB_BACKGROUND

设置用于“gfxterm”图形终端的背景图像。此选项的值必须是GRUB在引导时可读的文件,并且必须以‘.png’、‘.tga’、‘.jpg’或‘.jpeg’结尾。如果需要,图像将进行缩放以适应屏幕。

GRUB_THEME

设置与“gfxterm”图形终端一起使用的主题。

GRUB_DISABLE_SUBMENU

通常,grub-mkconfig将为具有最高版本号的内核生成顶级菜单项,并将所有其他找到的内核或恢复模式的可选菜单项放在子菜单中。对于由os-prober返回的条目,第一个条目将放在顶层,所有其他条目都放在子菜单中。如果此选项设置为‘y’,则将生成包含顶层所有条目的平面菜单。

GRUB_PRELOAD_MODULES

此选项可设置为由空格分隔的GRUB模块名称列表。每个模块将在“grub.cfg”开头尽早加载。

GRUB_DISABLE_OS_PROBER

通常情况下,grub-mkconfig将尝试使用外部os-prober程序(如果安装了)来发现安装在同一系统上的其他操作系统,并为它们生成适当的菜单项。将此选项设置为“true”以禁用此选项。

要更详细地定制grub-mkconfig的输出,可以直接在‘/etc/grub.d’中编辑脚本。‘/etc/grub.d/40_custom’对于添加整个自定义菜单项特别有用;只需键入要在文件末尾添加的菜单项,确保至少保留前两行完整。

 

直接制作全部的配置

‘grub.cfg’是用GRUB的内置脚本语言编写的,脚本语言的语法与GNU Bash和其他Bourne shell衍生工具非常相似。

words

words是被GRUB视为一个单元的一系列字符。words由元字符分隔,这些字符包括以下加空格、制表符和换行符:

{ } | & $ ; < >

保留words

保留words对GRUB有特殊的意义。下列words在未引用时被认为是保留的,或者是简单命令的第一个词,或者是for命令的第三个词:

! [[ ]] { }

case do done elif else esac fi for function
if in menuentry select then time until while

引用

引语用于删除某些字符或单词的特殊含义。它可以用来将元字符作为单词的一部分,防止保留词被识别为元字符,并防止变量扩展。

有三种引用机制:转义字符、单引号和双引号。

非引号反斜杠(\)是转义字符。它保留后面的下一个字符的字面值,但换行符除外。单引号不能出现在单引号之间,即使前面有反斜杠。

双引号括起来的字符保留引号中所有字符的字面值,但‘$’和‘\’除外。“$”字符在双引号中保留其特殊含义。反斜杠只有在后面跟着以下字符之一时才保留其特殊意义:‘$’、‘“、’\‘或换行符。反斜杠-换行符对被视为行延续(也就是说,从输入流中移除它,实际上忽略了)。双引号可以在双引号前加上反斜杠引用。

变量扩展

$字符引入变量扩展,要扩展的变量名可以用大括号括起来,这些大括号是可选的,但可以保护要扩展的变量不受紧跟在它后面的字符的影响,这些字符可以解释为名称的一部分。

变量名以字母字符开头,后面跟着零个或多个字母数字字符。

位置变量名由一个或多个数字组成。它们表示传递给函数调用的参数,‘$1’表示第一个参数,依此类推。

特殊变量名“?”表示最近执行的命令的退出状态。当位置变量名处于活动状态时,定义了其他特殊变量名称“@”、“*”和“#”,并将它们扩展到所有位置参数,位置参数和位置参数计数不需要括号。

注释

以“#”开头的单词会导致该单词和该行中的所有剩余字符被忽略。

简单命令

简单的命令是由空格或制表符分隔的一系列单词,以分号或换行符结尾。第一个单词指定要执行的命令,剩下的单词作为参数传递给被调用的命令。

简单命令的返回值是其退出状态。如果保留字符!在命令之前,则返回值是命令退出状态的逻辑否定。

复杂命令

for name in word . . .; do list; done

扩展in后面的word列表,生成项目列表。变量name依次设置为此列表的每个元素,每次执行List。返回值是执行的最后一个命令的退出状态。如果展开后的项导致一个空列表,则不执行任何命令,返回状态为0。

 

if list; then list; [elif list; then list;] . . . [else list;] fi

if list被执行,如果退出状态为零,则执行then list。否则,依次执行每个elif list,如果其退出状态为零,则执行相应的then list然后命令完成。否则,如果存在else,则执行else list。退出状态是执行的最后一个命令的退出状态或0(如果没有条件为true)。

 

while cond; do list; done
until cond; do list; done

while命令持续执行do list,只要cond中的最后一个命令返回退出状态为零。除cond是否定外,until命令与while命令相同;只要cond中的最后一个命令返回退出状态为非零,就会执行do list。while和until的退出状态是执行的最后一个do list命令的退出状态或0(如果没有执行)。

 

function name { command; . . . }

这定义了一个名为name的函数。函数的body是大括号中的命令列表,每个命令都必须以分号或换行符结尾。每当将name指定为简单命令的名称时,将执行此命令列表。函数定义不影响$?中的退出状态。执行时,函数的退出状态是body中执行的最后一个命令的退出状态。

 

menuentry title [‘--class=class’ . . .] [‘--users=users’] [‘--unrestricted’]
[‘--hotkey=key’] [‘--id=id’] { command; . . . }

这定义了一个名为title的GRUB菜单项。当从菜单中选择此条目时,GRUB将设置环境变量chosen为‘--id’的值(如果--id设置),执行在大括号内给出的命令列表,如果列表中的最后一个命令成功返回并加载了内核,它将执行boot命令。

 

内置命令

break [n]

从for、while或until循环内退出。如果指定n,则打破n级。n必须大于或等于1。如果n大于环数,则所有封闭环都退出。返回值为0,除非n不大于或等于1。

 

continue [n]
继续下一次循环。如果指定了n,则在第n个封闭循环处继续。n必须大于或等于1。如果n大于循环数,则恢复最后一个循环(顶层循环)。返回值为0,除非n不大于或等于1。

 

return [n]

使函数以n指定的返回值退出。如果省略n,则返回状态是函数体中执行的最后一个命令的状态。如果在函数之外使用,则返回状态为false。

 

setparams [arg] . . .

将以$1开头的位置参数替换为setparams的参数。

 

shift [n]

n+1的位置参数被重命名为$1,参数数量$#变为$#-n+1,n必须是小于或等于$#的非负数。如果n为0时,则不改变参数。如果不给出n,则假定为1。如果n大于$#,则位置参数不会更改。如果n大于$#或小于零,则返回状态大于零;否则为0。

 

将配置文件嵌入GRUB

GRUB支持将配置文件直接嵌入到核心映像中,以便在进入正常模式之前加载配置文件。例如,当找到真正的配置文件并不简单时,或者当您需要调试加载该文件的问题时,这是非常有用的。grub-install在不使用BIOS磁盘功能或安装到与包含‘/boot/grub’的磁盘不同的磁盘时使用此特性,在这种情况下,它需要使用search命令查找‘/boot/grub’。

若要嵌入配置文件,使用“-c”选项执行grub-mkimage进行嵌入。该文件被复制到核心映像中,因此它可以在文件系统的任何位置,并且可以运行grub-mkimage删除。

执行嵌入式配置文件(如果有的话)后,GRUB将加载“normal”模块,然后从‘$prefix/grub.cfg’读取真正的配置文件。至此,root变量也将设置为根设备名称。例如,可以将前缀设置为"(hd0,1)/boot/grub",并且可以将root设置为"hd0,1"。因此,在大多数情况下,嵌入式配置文件只需要设置prefix和root变量,然后进入GRUB的正常处理。例如:

search.fs_uuid 01234567-89ab-cdef-0123-456789abcdef root
set prefix=($root)/boot/grub

(核心image中必须包含模块search_fs_uuid)

 

在更复杂的情况下,直接从嵌入式配置文件读取其他配置文件可能很有用。这允许读取不称为“grub.cfg”的文件,或者从安装了GRUB可加载模块的目录中读取文件。为此,在核心image中包括“configfile”和“Normal”模块,并嵌入使用configfile命令加载另一个配置文件。以下示例还要求将echo、search_label和test模块包括在核心image中:

search.fs_label grub root
if [ -e /boot/grub/example/test1.cfg ]; then
  set prefix=($root)/boot/grub
  configfile /boot/grub/example/test1.cfg
else
    if [ -e /boot/grub/example/test2.cfg ]; then
      set prefix=($root)/boot/grub
      configfile /boot/grub/example/test2.cfg
    else
      echo "Could not find an example configuration file!"
    fi
fi

嵌入的配置文件可能不直接包含菜单条目,但是可以仅使用configfile从其他地方读取它们。

 

GRUB image文件

GRUB由几个image组成:用于以各种方式启动GRUB的各种引导image、内核image和一组与内核image相结合的模块,以形成核心image。

 

boot.img

在PC BIOS系统上,这个image是GRUB启动的第一部分。它被写入主引导记录(MBR)或分区的引导扇区。因为PC引导扇区是512字节,这个image的大小正好是512字节。

‘boot.img’的唯一功能是从本地磁盘读取核心image的第一个扇区并跳转到它。由于大小限制,‘boot.img’无法理解所有文件系统结构,所以在安装GRUB时,grub-install将核心image的第一个扇区的位置硬编码到‘boot.img’中。

 

diskboot.img

当从硬盘启动时,这个image被用作核心image的第一个扇区。它将核心image的其余部分读入内存并启动内核。由于还没有可用的文件系统,所以它使用块列表格式对核心image的位置进行编码。

 

cdboot.img

当从CD-ROM驱动器启动时,这个image被用作核心image的第一个扇区。它执行类似于“diskboot.img”的功能。

 

pxeboot.img

当使用PXE从网络启动时,该image用作核心image的开始。

 

lnxboot.img

这个image可以放在核心image的开头,以便使GRUB看起来足够像Linux内核,以便Lilo可以使用“image=”部分引导它。

 

kernel.img

此image包含GRUB的基本运行时工具:设备和文件处理框架、环境变量、救援模式命令行解析器等。它很少直接使用,而是内置于所有核心image中。

 

core.img

这是GRUB的核心image。它是由grub-mkimage程序从内核image和任意模块列表动态构建的。通常,它包含足够多的模块来访问‘/boot/grub’,并在运行时从文件系统加载所有其他内容(包括菜单处理、加载目标操作系统的能力等等)。模块化设计允许核心image保持较小,因为必须安装的磁盘区域通常小到32 KB。

 

*.mod

GRUB中的所有其他内容都驻留在可动态加载的模块中。这些都是通常是自动加载的,或者如果是必需的,则内置到核心image中,但也可以使用insmod命令手动加载

 

对于GRUB Legacy用户

GRUB 2与GRUB Legacy有不同的设计,因此与它使用的image的对应不一样。

 

stage1

GRUB Legacy的stage 1与GRUB 2中的‘boot.img’非常相似,它们提供相同的功能。

 

*_stage1_5

在GRUB Legacy中,stage1.5的功能是包含足够多的文件系统代码,以允许从普通文件系统读取更大的stage2。在这方面,它的功能类似于GRUB 2中的“core.img”。但是,“core.img”的能力要比State1.5强得多;由于它提供了一个救援shell,因此有时可以在无法加载任何其他模块时手动恢复,例如,如果分区号发生了更改。“core.img”是以更灵活的方式构建的,允许GRUB 2支持从高级磁盘类型(如LVM和RAID)读取模块。

 

stage2

GRUB 2没有单一的stage2。相反,它在运行时从‘/boot/grub’加载模块。

 

stage2_eltorito

在GRUB 2中,现在使用‘cdboot.img’和‘core.img’构建用于从CD-ROM驱动器引导的image,确保核心image包含“iso9660”模块。通常最好使用grub-mkrescue程序构建。

 

nbgrub

到目前为止,GRUB 2中的‘nbgrub’还没有对应的模块;它被Etherboot和其他一些网络引导加载程序使用。

 

pxegrub

在GRUB 2中,用于PXE网络引导的映像现在使用‘pxeboot.img’和‘core.img’构建,确保核心image包含‘pxe’和‘pxecmd’模块。

 

 

猜你喜欢

转载自blog.csdn.net/byrgzs/article/details/86526575