详解grub(二)

四、各种img和stage文件的说明

img文件是grub2生成的,stage文件是传统grub生成的。下面是各种文件的说明。

grub2中的img文件

grub2生成了好几个img文件,有些分布在/usr/lib/grub/i386-pc目录下,有些分布在/boot/grub2/i386-pc目录下。
在这里插入图片描述
下图描述了各个img文件之间的关系。其中core.img是动态生成的,路径为/boot/grub2/i386-pc/core.img,而其他的img则存在于/usr/lib/grub/i386-pc目录下。当然,在安装grub时,boot.img会被拷贝到/boot/grub2/i386-pc目录下。
在这里插入图片描述
(1)boot.img

在BIOS平台下,boot.img是grub启动的第一个img文件,它被写入到MBR中或分区的boot sector中,因为boot sector的大小是512字节,所以该img文件的大小也是512字节。

boot.img唯一的作用是读取属于core.img的第一个扇区并跳转到它身上,将控制权交给该扇区的img。由于体积大小的限制,boot.img无法理解文件系统的结构,因此grub2-install将会把core.img的位置硬编码到boot.img中,这样就一定能找到core.img的位置。

(2)core.img

core.img根据diskboot.img、kernel.img和一系列的模块被grub2-mkimage程序动态创建。core.img中嵌入了足够多的功能模块以保证grub能访问/boot/grub,并且可以加载相关的模块实现相关的功能,例如加载启动菜单、加载目标操作系统的信息等,由于grub2大量使用了动态功能模块,使得core.img体积变得足够小。

core.img中包含了多个img文件的内容,包括diskboot.img/kernel.img等。

core.img的安装位置随MBR磁盘和GPT磁盘而不同,这在上文中已经说明过了。

(3)diskboot.img

如果启动设备是硬盘,即从硬盘启动时,core.img中的第一个扇区的内容就是diskboot.img。diskboo.img的作用是读取core.img中剩余的部分到内存中,并将控制权交给kernel.img,由于此时还不识别文件系统,所以将core.img的全部位置以block列表的方式编码,使得diskboot.img能够找到剩余的内容。

该img文件因为占用一个扇区,所以体积为512字节。

(4)cdboot.img

如果启动设备是光驱(cd-rom),即从光驱启动时,core.img中的第一个扇区的的内容就是cdboo.img。它的作用和diskboot.img是一样的。

(5)pexboot.img

如果是从网络的PXE环境启动,core.img中的第一个扇区的内容就是pxeboot.img。

(6)kernel.img

kernel.img文件包含了grub的基本运行时环境:设备框架、文件句柄、环境变量、救援模式下的命令行解析器等等。很少直接使用它,因为它们已经整个嵌入到了core.img中了。注意,kernel.img是grub的kernel,和操作系统的内核无关。

如果细心的话,会发现kernel.img本身就占用28KB空间,但嵌入到了core.img中后,core.img文件才只有26KB大小。这是因为core.img中的kernel.img是被压缩过的。

(7)lnxboot.img

该img文件放在core.img的最前部位,使得grub像是linux的内核一样,这样core.img就可以被LILO的"image="识别。当然,这是配合LILO来使用的,但现在谁还适用LILO呢?

(8)*.mod

各种功能模块,部分模块已经嵌入到core.img中,或者会被grub自动加载,但有时也需要使用insmod命令手动加载。

传统grub中的stage文件

stage文件也分布在两个地方:/usr/share/grub/RELEASE目录下和/boot/grub目录下,/boot/grub目录下的stage文件是安装grub时从/usr/share/grub/RELEASE目录下拷贝过来的。
在这里插入图片描述
(1)stage1

stage1文件在功能上等价于boot.img文件。目的是跳转到stage1_5或stage2的第一个扇区上。

(2)*_stage1_5

*stage1_5文件包含了各种识别文件系统的代码,使得grub可以从文件系统中读取体积更大功能更复杂的stage2文件。从这一方面考虑,它类似于core.img中加载对应文件系统模块的代码部分,但是core.img的功能远比stage1_5多。

stage1_5一般安装在MBR后、第一个分区前的那段空闲空间中,也就是MBR gap空间,它的作用是跳转到stage2的第一个扇区。

其实传统的grub在某些环境下是可以不用stage1_5文件就能正常运行的,但是grub2则不能缺少core.img。

(3)stage2

stage2的作用是加载各种环境和加载内核,在grub2中没有完全与之相对应的img文件,但是core.img中包含了stage2的所有功能。

当跳转到stage2的第一个扇区后,该扇区的代码负责加载stage2剩余的内容。

注意,stage2是存放在磁盘上的,并没有像core.img一样嵌入到磁盘上。

(4)stage2_eltorito

功能上等价于grub2中的core.img中的cdboot.img部分。一般在制作救援模式的grub时才会使用到cd-rom相关文件。

(5)pxegrub

功能上等价于grub2中的core.img中的pxeboot.img部分。

五、grub2配置文件

grub2的默认配置文件为/boot/grub2/grub.cfg,该配置文件的写法弹性非常大,但绝大多数需要修改该配置文件时,都只需修改其中一小部分内容就可以达成目标。

grub2-mkconfig程序可用来生成符合绝大多数情况的grub.cfg文件,默认它会自动尝试探测有效的操作系统内核,并生成对应的操作系统菜单项。使用方法非常简单,只需一个选项"-o"指定输出文件即可。

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

通过/etc/default/grub文件生成grub.cfg

官方手册原文

grub2-mkconfig是根据/etc/default/grub文件来创建配置文件的。 该文件中定义的是grub的全局宏,修改内置的宏可以快速生成grub配置文件。实际上在/etc/grub.d/目录下还有一些grub配置脚本,这些shell脚本读取一些脚本配置文件(如/etc/default/grub),根据指定的逻辑生成grub配置文件。若有兴趣,不放读一读/etc/grub.d/10_linux文件,它指导了创建grub.cfg的细节,例如如何生成启动菜单。

在这里插入图片描述

在/etc/default/grub中,使用"key=vaule"的格式,key全部为大小字母,如果vaule部分包含了空格或其他特殊字符,则需要使用引号包围。

例如,下面是一个/etc/default/grub文件的示例:
在这里插入图片描述
虽然可用的宏较多,但可能用的上的就几个:GRUB_DEFAULT、GRUB_TIMEOUT、GRUB_CMDLINE_LINUX和GRUB_CMDLINE_LINUX_DEFAULT。

以下列出了部分key。

(1).GRUB_DEFAULT

默认的菜单项,默认值为0。其值可为数值N,表示从0开始计算的第N项是默认菜单,也可以指定对应的title表示该项为默认的菜单项。使用数值比较好,因为使用的title可能包含了容易改变的设备名。例如有如下菜单项:

menuentry 'Example GNU/Linux distribution' --class gnu-linux --id example-gnu-linux {
    ...
}

如果想将此菜单设为默认菜单,则可设置"GRUB_DEFAULT=example-gnu-linux"

如果GRUB_DEFAULT的值设置为"saved",则表示默认的菜单项是"GRUB_SAVEDEFAULT""grub-set-default"所指定的菜单项。

(2).GRUB_SAVEDEFAULT

默认该key的值未设置。如果该key的值设置为true时,如果选定了某菜单项,则该菜单项将被认为是新的默认菜单项。该key只有在设置了"GRUB_DEFAULT=saved"时才有效。

不建议使用该key,因为GRUB_DEFAULT配合grub-set-default更方便。

(3).GRUB_TIMEOUT

在开机选择菜单项的超时时间,超过该时间将使用默认的菜单项来引导对应的操作系统。默认值为5秒。等待过程中,按下任意按键都可以中断等待。

设置为0时,将不列出菜单直接使用默认的菜单项引导与之对应的操作系统,设置为"-1"时将永久等待选择。

是否显示菜单,和"GRUB_TIMEOUT_STYLE"的设置有关。

(4).GRUB_TIMEOUT_STYLE

如果该key未设置值或者设置的值为"menu",则列出启动菜单项,并等待"GRUB_TIMEOUT"指定的超时时间。

如果设置为"countdown""hidden",则不显示启动菜单项,而是直接等待"GRUB_TIMEOUT"指定的超时时间,如果超时了则启动默认菜单项并引导对应的操作系统。在等待过程中,按下"ESC"键可以列出启动菜单。设置为countdownhidden的区别是countdown会显示超时时间的剩余时间,而hidden则完全隐藏超时时间。

(5).GRUB_DISTRIBUTOR

设置发行版的标识名称,一般该名称用来作为菜单的一部分,以便区分不同的操作系统。

(6).GRUB_CMDLINE_LINUX

添加到菜单中的内核启动参数。例如:

GRUB_CMDLINE_LINUX="crashkernel=ro root=/dev/sda3 biosdevname=0 net.ifnames=0 rhgb quiet"

(7).GRUB_CMDLINE_LINUX_DEFAULT

除非"GRUB_DISABLE_RECOVERY"设置为"true",否则该key指定的默认内核启动参数将生成两份,一份是用于默认启动参数,一份用于恢复模式(recovery mode)的启动参数。

该key生成的默认内核启动参数将添加在"GRUB_CMDLINE_LINUX"所指定的启动参数之后。

(8).GRUB_DISABLE_RECOVERY

该项设置为true时,将不会生成恢复模式的菜单项。

(9).GRUB_DISABLE_LINUX_UUID

默认情况下,grub2-mkconfig在生产菜单项的时候将使用uuid来标识Linux 内核的根文件系统,即"root=UUID=…"。

例如,下面是/boot/grub2/grub.cfg中某菜单项的部分内容。

menuentry 'CentOS Linux (3.10.0-327.el7.x86_64) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-327.el7.x86_64-advanced-b2a70faf-aea4-4d8e-8be8-c7109ac9c8b8' {
        ......

        linux16 /vmlinuz-3.10.0-327.el7.x86_64 root=UUID=b2a70faf-aea4-4d8e-8be8-c7109ac9c8b8 ro crashkernel=auto biosdevname=0 net.ifnames=0 quiet LANG=en_US.UTF-8

        initrd16 /initramfs-3.10.0-327.el7.x86_64.img

}

虽然使用UUID的方式更可靠,但有时候不太方便,所以可以设置该key为true来禁用。

(10).GRUB_BACKGROUND

设置背景图片,背景图片必须是grub可读的,图片文件名后缀必须是".png"、“.tga”、“.jpg”、“.jpeg”,在需要的时候,grub会按比例缩小图片的大小以适配屏幕大小。

(11).GRUB_THEME

设置grub菜单的主题。

(12).GRUB_GFXPAYLOAD_LINUX

设置为"text"时,将强制使用文本模式启动Linux。在某些情况下,可能不支持图形模式。

(13).GRUB_DISABLE_OS_PROBER

默认情况下,grub2-mkconfig会尝试使用os-prober程序(如果已经安装的话,默认应该都装了)探测其他可用的操作系统内核,并为其生成对应的启动菜单项。设置为"true"将禁用自动探测功能。

(14).GRUB_DISABLE_SUBMENU

默认情况下,grub2-mkconfig如果发现有多个同版本的或低版本的内核时,将只为最高版本的内核生成顶级菜单,其他所有的低版本内核菜单都放入子菜单中,设置为"y"将全部生成为顶级菜单。

(15).GRUB_HIDDEN_TIMEOUT(已废弃,但为了向后兼容,仍有效)

使用"GRUB_TIMEOUT_STYLE={countdown|hidden}"替代该项

(16).GRUB_HIDDEN_TIMEOUT_QUIET(已废弃,但为了向后兼容,仍有效)

配合GRUB_HIDDEN_TIMEOUT使用,可以使用GRUB_TIMEOUT_STYLE=countdown来替代这两项。

脚本方式直接编写grub.cfg文件

官方手册原文

  • 注释符:从#开始的字符都被认为是注释,所以grub支持行中注释

  • 连接操作符:{ } | & $ ; < >

  • 保留关键字和符号:! [[ ]] { } case do done elif else esac fi for function if in menuentry select then time until while。并非所有的关键字都有用,只是为了日后的功能扩展而提前提供的。

  • 引号和转义符
    对于特殊的字符需要转义。有三种方式转义:使用反斜线、使用单引号、使用双引号。

    反斜线转义方式和shell一样。

    单引号中的所有字符串都是字面意思,没有任何特殊意义,即使单引号中的转义符也被认为是纯粹的字符。所以’'‘是无法保留单引号的。单引号需要使用双引号来转移,所以应该写"’"。

    双引号和单引号作用一样,但它不能转义某几个特殊字符,包括" " 和 " 。 ¨ 对于双引号中的 " "和"\"。对于双引号中的" ""¨对于双引号中的"“符号,它任何时候都保留本意。对于”“,只有反斜线后的字符是’$‘、’”‘、’'时才表示转义的意思,另外 ,某行若以反斜线结尾,则表示续行,但官方不建议在grub.cfg中使用续行符。

  • 变量扩展
    使用 符号引用变量,也可以使用 符号引用变量,也可以使用 符号引用变量,也可以使用{var}的方式引用var变量。

    支持位置变量,例如$1引用的是第一个参数。

    还支持特殊的变量,如 ? 表示上一次命令的退出状态码。如果使用了位置变量,则还支持 ?表示上一次命令的退出状态码。如果使用了位置变量,则还支持 ?表示上一次命令的退出状态码。如果使用了位置变量,则还支持*、 @ 和 @和 @#, ∗ 代表的所有参数整体,各参数之间是不可分割的, *代表的所有参数整体,各参数之间是不可分割的, 代表的所有参数整体,各参数之间是不可分割的,@也代表所有变量,但 @ 的各参数是可以被分割的, @的各参数是可以被分割的, @的各参数是可以被分割的,#表示参数的个数。

  • 简单的命令
    可以在grub.cfg中使用简单的命令。各命令之间使用换行符或分号表示该命令结束。

    如果在命令前使用了"!",则表示逻辑取反。

  • 循环结构:for name in word …; do list; done

  • 循环结构:while cond; do list; done

  • 循环结构:until cond; do list; done

  • 条件判断结构:if list; then list; [elif list; then list;] … [else list;] fi

  • 函数结构:function name { command; … }

  • 菜单项命令:menuentry title [–class=class …] [–users=users] [–unrestricted] [–hotkey=key] [–id=id] { command; … }
    这是grub.cfg中最重要的项,官方原文

    该命令定义了一个名为title的grub菜单项。当开机时选中该菜单项时,grub会将chosen环境变量的值赋给"–id"(如果给定了"–id"的话),执行大括号中的命令列表,如果直到最后一个命令都全部执行成功,且成功加载了对应的内核后,将执行boot命令。随后grub就将控制权交给了操作系统内核。

    –class:该选项用于将菜单分组,从而使得grub可以通过主题样式为不同组的菜单显示不同的样式风格。一个menuentry中,可以使用多次class表示将该菜单分到多个组中去。

    –users:该选项限定只有此处列出的用户才能访问该菜单项,不指定该选项时将表示所有用户都能访问该菜单。

    –unrestricted:该选项表示所有用户都有权访问该菜单项。

    –hotkey:该选项为该菜单项关联一个热键,也就是快捷键,关联热键后只要按下该键就会选中该菜单。热键只能是字母键、backspace键、tab键或del键。

    –id:该选项为该菜单关联一个唯一的数值。id的值可以由ASCII字母、数字//下划线组成,且不得以数字开头。

    所有其他的参数包括title都被当作位置参数传递给大括号中的命令,但title总是$1,除title外的其余参数,位置值从前向后类推。

  • break [n]:强制退出for/while/until循环

  • continue [n]:跳到下一次迭代,即进入下一次循环

  • return [n]:指定返回状态码

  • setparams [arg] …:从$1开始替换位置参数

  • shift [n]:踢掉前n个参数,使得第n+1个参数变为$ 1,但和shell中不一样的是,踢掉了前n个参数后,从KaTeX parse error: Expected 'EOF', got '#' at position 1: #̲-n+1到#这些参数的位置不变

grub环境

在linux或linux16命令之后,必须紧跟着使用init或init16命令装载init ramdisk文件。

一般为/boot分区下的vmlinuz-RELEASE_NUM文件。

但在grub环境下,boot分区被当作root分区,即根分区,假如boot分区为第一块磁盘的第一个分区,则应该写成:

linux (hd0,msdos1)/vmlinuz-XXX

或者相对路径的:

set root=‘hd0,msdos1’

linux /vmlinuz-XXX

在grub阶段可以传递内核的启动参数(内核的参数包括3类:编译内核时参数,启动时参数和运行时参数),可以传递的启动参数非常非常多,完整的启动参数列表见:http://redsymbol.net/linux-kernel-boot-parameters。这里只列出几个常用的:

init= :指定Linux启动的第一个进程init的替代程序。
root= :指定根文件系统所在分区,在grub中,该选项必须给定。
ro,rw :启动时,根分区以只读还是可读写方式挂载。不指定时默认为ro。
initrd :指定init ramdisk的路径。在grub中因为使用了initrd或initrd16命令,所以不需要指定该启动参数。
rhgb :以图形界面方式启动系统。
quiet :以文本方式启动系统,且禁止输出大多数的log message。
net.ifnames=0:用于CentOS 7,禁止网络设备使用一致性命名方式。
biosdevname=0:用于CentOS 7,也是禁止网络设备采用一致性命名方式。
:只有net.ifnames和biosdevname同时设置为0时,才能完全禁止一致性命名,得到eth0-N的设备名。
例如:

linux16 /vmlinuz-3.10.0-327.el7.x86_64 root=UUID=edb1bf15-9590-4195-aa11-6dac45c7f6f3 ro rhgb quiet LANG=en_US.UTF-8

另外,root启动参数有多种定义方式,可以使用UUID的方式指定,也可以直接指定根文件系统所在分区,如"root=/dev/sda2",

六、 grub配置和安装示例

grub.conf示例

首先写一个grub.cfg。例如此处,在msdos磁盘上安装了两个操作系统,CentOS 7和CentOS 6。

# 设置一些全局环境变量
set default=0
set fallback=1
set timeout=3

# 将可能使用到的模块一次性装载完
# 支持msdos的模块
insmod part_msdos
# 支持各种文件系统的模块
insmod exfat
insmod ext2
insmod xfs
insmod fat
insmod iso9660

# 定义菜单
menuentry 'CentOS 7' --unrestricted {
        search --no-floppy --fs-uuid --set=root 367d6a77-033b-4037-bbcb-416705ead095
        linux16 /vmlinuz-3.10.0-327.el7.x86_64 root=UUID=b2a70faf-aea4-4d8e-8be8-c7109ac9c8b8 ro biosdevname=0 net.ifnames=0 quiet
        initrd16 /initramfs-3.10.0-327.el7.x86_64.img
}
menuentry 'CentOS 6' --unrestricted {
        search --no-floppy --fs-uuid --set=root f5d8939c-4a04-4f47-a1bc-1b8cbabc4d32
        linux16 /vmlinuz-2.6.32-504.el6.x86_64 root=UUID=edb1bf15-9590-4195-aa11-6dac45c7f6f3 ro quiet
        initrd16 /initramfs-2.6.32-504.el6.x86_64.img
}

然后执行grub安装操作。

shell> grub2-install /dev/sda

旧版GRUB grub.conf配置

default=0  # 默认启动第一个系统
timeout=5  # 等待超时时间5秒
splashimage=(hd0,0)/grub/splash.xpm.gz  # 背景图片
hiddenmenu  # 隐藏菜单,若要显式,在启动时按下ESC
title Red Hat Enterprise Linux AS (2.6.18-92.el5)  # 定义操作系统的说明信息
    root (hd0,0) 
    kernel /vmlinuz-2.6.18-92.el5 ro root=/dev/sda2 rhgb quiet
    initrd /initrd-2.6.18-92.el5.img

在说明配置方法之前,需要说明一个关键点,boot是否是一个独立的分区,它影响后面路径的配置。

在一个正常的操作系统中查看/boot/grub/grub.conf文件,可以在NOTICE段看到提示,说你是否拥有一个独立的boot分区?如果有则意味着kernelinitrd的路径是从/开始的而不是/boot开始的,如/vmlinuz-xxx,如果没有独立的boot分区,则kernelinitrd的路径中需要指明boot路径,例如Boot没有分区而是在/文件系统下的一个目录,则/boot/vmlinuz-xxx

root (hd0,0)定义grub识别的根。一般定义的都是boot所在的分区,grub只能识别hd,所以这里只能使用hdhd0表示在第一块磁盘上,hd0,0的第二个0表示boot在第一个分区上,grub2在分区的计算上是从1开始的,这是传统grub和grub2不同的地方

kernel定义内核文件的路径和启动参数,等价于grub2的linux命令或linux16命令。首先说明参数,ro表示只读,root=/dev/sda[N]或者root=UUID="device_uuid_num"指定根文件系统所在的分区,这是必须的参数。rhgb表示在操作系统启动过程中使用图形界面输出一些信息,将其省略可以加快启动速度,quiet表示启动操作系统时静默输出信息。再说明路径,如果是boot是独立分区的,则kernel的路径定义方式为/vmlinuz-xxx,如果没有独立分区,则指明其绝对路径,一般都是在根文件系统下的目录,所以一般为/boot/vmlinuz-xxx

initrd定义init ramdisk的路径,路径的定义方式同kernel。除了路径之外没有任何参数。

在这里插入图片描述
或者使用下图的UUID的方式。
在这里插入图片描述
如果没有指定root=的选项,将报错“no or empty root …… dracut…kernel panic”的错误。如下图。
在这里插入图片描述

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在CentOS中安装GRUB有两种方法,一种是通过已经安装好的GRUB配置文件进行修改,另一种是手动建立GRUB配置文件。 如果已经安装好GRUB,可以直接修改/boot/grub/grub.conf配置文件。打开终端并以管理员身份登录,输入以下命令: ``` sudo vi /boot/grub/grub.conf ``` 接下来,你可以看到配置文件的内容。你可以根据需要进行修改,例如设置默认启动项、设置超时时间等。保存并退出文件。 如果是尚未安装GRUB的Linux系统,你需要手动建立GRUB配置文件。打开终端并以管理员身份登录,输入以下命令: ``` sudo vi /boot/grub/grub.conf ``` 然后,根据你的需求添加以下内容到配置文件中: ``` default=0 timeout=5 splashimage=(hd0,0)/grub/splash.xpm.gz hiddenmenu title CentOS (2.6.32-279.el6.i686) root(hd0,0) kemel/vmlinuz-2.6.32-279.el6.i686 ro root=UUID=b9a7a1a8-767f-4a87-8a2ba535edb362c9 rd_NO_LUKS KEYBOARDTYPE=pc KEYTABLE=us rd_NO_MD crashkemel=auto LANG=zh_CN.UTF-8 rd_NO_LVM rd_NO_DM rhgb quiet initrd/initramfs-2.6.32-279.el6.i686.img title CentOS tdisk root(hd1,0) chainloader 1 ``` 在配置文件中,你可以根据需要修改默认启动项、超时时间、背景图像等。保存并退出文件。 另外,需要注意的是,如果系统中没有grub-install命令,则说明没有安装GRUB软件。你可以使用源码包安装或者使用RPM包安装。如果你选择使用RPM包安装,可以使用以下命令: ``` sudo yum -y install grub ``` 这样,你就完成了在CentOS中安装GRUB的步骤。 参考资料: Linux GRUB手动安装方法详解 [2] Linux学习-72-GRUB加密方法(2种加密方式)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值