三、Boot loader: Grub2
1.Boot loader的两个stage
之前讲过,在BIOS读取完信息后,就是到第一个开机设备的MBR去读取boot loader,这个boot loader有菜单功能、直接载入核心文件以及控制权移交的功能等。系统必须要有loader才有办法加载操作系统的核心,但是我们都知道,MBR是整个硬盘的第一个sector内的一块,充其量也就446bytes,即使GPT也没有很大空间存储loader的数据,那么我们的loader是如何安装呢?
为了解决这个问题,Linux把boot loader的源码执行与设定值加载分为了两个阶段来执行:
(1)STAGE 1:执行boot loader主程序。这个主程序必须要安装在开机区,也就是MBR或者boot sector。因为MBR太小,所以MBR或boot sector通常只安装boot loader的最小主程序,并没有安装loader的相关配置文件。
(2)STAGE 2:主程序载入配置文件。通过boot loader加载所有配置文件与相关的环境参数配置文件(包括文件系统定义与主要配置文件grub.cfg)。一般来说,配置文件都在/boot下面。我们查看一下grub下面就可以了,ubuntu目录为/boot/grub,Cent OS 7.x为/boot/grub2。如图3.1所示。
图3.1 grub里面的文件
root@xiaoao-virtual-machine:/home/xiaoao# ls -l /boot/grub/i386-pc 总用量 2440 -rw-r–r– 1 root root 7972 9月 5 22:08 915resolution.mod -rw-r–r– 1 root root 10620 9月 5 22:08 acpi.mod -rw-r–r– 1 root root 1324 9月 5 22:08 adler32.mod -rw-r–r– 1 root root 5652 9月 5 22:08 affs.mod -rw-r–r– 1 root root 6108 9月 5 22:08 afs.mod -rw-r–r– 1 root root 15540 9月 5 22:08 ahci.mod -rw-r–r– 1 root root 492 9月 5 22:08 all_video.mod -rw-r–r– 1 root root 1036 9月 5 22:08 aout.mod -rw-r–r– 1 root root 2956 9月 5 22:08 archelp.mod -rw-r–r– 1 root root 5636 9月 5 22:08 ata.mod -rw-r–r– 1 root root 4284 9月 5 22:08 at_keyboard.mod -rw-r–r– 1 root root 1640 9月 5 22:08 backtrace.mod -rw-r–r– 1 root root 6816 9月 5 22:08 bfs.mod -rw-r–r– 1 root root 4692 9月 5 22:08 biosdisk.mod -rw-r–r– 1 root root 2256 9月 5 22:08 bitmap.mod -rw-r–r– 1 root root 3788 9月 5 22:08 bitmap_scale.mod -rw-r–r– 1 root root 2128 9月 5 22:08 blocklist.mod -rw-r–r– 1 root root 512 9月 5 22:08 boot.img -rw-r–r– 1 root root 2432 9月 5 22:08 boot.mod (以下全部省略) |
2.grub2的配置文件grub.cfg初探
安装在MBR的grub2的主程序最重要的任务是从硬盘中加载核心文件,让核心能够顺利驱动整个系统的硬件,所以grub2必须认识硬件才可以。grub2对硬件的代码设置与传统Linux硬盘代号完全不同,rub2对硬盘的识别是用以下代码:
(hd0,1) #一般的默认语法,由grub2自动判断分割格式 (hd0,msdos1)#此磁盘的分割为传统的MBR模式 (hd0,gpt1)#此磁盘的分割为GPT模式 |
这里面主要的是:
①硬盘代号以小括号()包起来;
②硬盘以hd表示,后面会接一组数字;
③以『搜寻顺序』做为硬盘的编号:第一个搜寻到的硬盘为0号,第二个为1号,以此类推;
④每个硬盘的第一个partition代号为1,依序类推。
如上所示,第一个搜索到的硬盘代号为(hd0),而该硬盘的第一个分割槽为1。当然,为了区分不同的分割格式,1前面会加上gpt或者msdos等标识。要记住,硬盘变好从0开始,分割槽编号从1开始。
(1)/boot/grub2/grub.cfg配置文件(不可修改)
在grub.cfg最开始的部份,其实大多是环境设定与默认值设定等,比较重要的当然是默认由哪个选项开机(set default)以及预设的秒数(set timeout),再来则是每一个菜单的设定,就是在『menuentry』这个设定值之后的项目。
在menuentry之后会有几个项目的规范,包括『–class,–unrestricted –id』等等的指定项目,之后通过『{}』将这个菜单会用到的数据框起来,在选择这个菜单之后就会进行括号内的动作的意思。如果真的点选了这个菜单,那grub2首先会加载模块。之后就是三个比较重要的项目:
①set root=’hd0,gpt2′
这里的root是指定grub2配置文件所在的那个设备。以我们的测试机来说,当初安装的时候分割出/与/boot两个设备,而grub2是在/boot/grub2这个设备上,而这个位置的磁盘文件名为/dev/vda2,因此完整的grub2磁盘名称就是(hd0,2)。因为我们的系统用的是GPT的磁盘分区格式,因此全名就是『hd0,gpt2』。
②linux16 /vmlinuz-… root=/dev/mapper/centos-root …
这个就是 Linux 核心文件以及核心执行时所下达的参数。你应该会觉得比较怪的是,我们的核心文件不是 /boot/vmlinuz-xxx 吗? 怎么这里的设定会是在根目录呢?这个跟上面的 root 有关啦!大部分的系统大多有 /boot 这个分割槽,如果 /boot 没有分割, 那会是怎么回事呢?我们用底下的迭代来说明一下:
如果没有 /boot 分割,仅有 / 分割:所以文件名会这样变化喔:
/boot/vmlinuz-xxx –> (/)/boot/vmlinuz-xxx –> (hd0,msdos1)/boot/vmlinuz-xxx
如果 /boot 是独立分割,则文件名的变化会是这样:
/boot/vmlinuz-xxx –> (/boot)/vmlinuz-xxx –> (hd0,msdos1)/vmlinuz-xxx
因此,这个 linux16 后面接的文件名得要跟上面的 root 搭配在一起,才是完整的绝对路径文件名喔!看懂了吗?至于 linux16 /vmlinuz-xxx root=/file/name 那个 root 指的是『 linux 文件系统中,根目录是在哪个装置上』的意思!从本章一开始的开机流程中,我们就知道核心会主动去挂载根目录,并且从根目录中读取配置文件, 再进一步开始开机流程。所以,核心文件后面一定要接根目录的装置啊!这样理解吧?我们从 /etc/fstab 里面也知道根目录的挂载可以是装置文件名、 UUID 与 LABEL 名称,因此这个 root 后面也是可以带入类似 root=UUID=1111.2222.33… 之类的模式喔!
③initrd16 /initramfs-3.10…
这个就是initramfs所在的檔名,跟linux16那个vmlinuz-xxx相同,这个档名也是需要搭配『se troot=xxx』那个项目的装置,才会得到正确的位置。
3.grub2配置文件维护/etc/default/grub与/etc/grub.d:grub,40_custom
我们可以通过/etc/default/grub这个主要环节配置文件与/etc/grub.d/目录中的相关配置文件来处理比较好。
(1)/etc/default/grub环境配置文件
我们查看一下这个文件,执行“cat /etc/default/grub”,可以得到如图3.2所示的情况。
图3.2 /etc/default/grub环境配置文件情况
如下所示是CentOS 7.x的情况:
[root@study ~]# cat /etc/default/grub GRUB_TIMEOUT=5 # 指定预设倒数读秒的秒数 GRUB_DEFAULT=saved # 指定预设由哪一个菜单来开机,预设开机菜单之意 GRUB_DISABLE_SUBMENU=true # 是否要隐藏次菜单,通常是藏起来比较好。 GRUB_TERMINAL_OUTPUT=”console” #指定数据输出的终端机格式,默认通过文字终端机 GRUB_CMDLINE_LINUX=”rd.lvm.lv=centos/root rd.lvm.lv=centos/swap crashkernel=auto rhgb quiet” # 就是在 menuentry 括号内的 linux16 项目后续的核心参数 GRUB_DISABLE_RECOVERY=”true” # 取消修复菜单的制作 |
主要几个项目解释如下:
①倒数时间参数:GRUB_TIMEOUT
这个设定值相当简单,后面就是接你要倒数的秒数即可。如果不想等待则输入0,如果一定让用户选择,则填-1即可。
②是否隐藏菜单项目:GRUB_TIMEOUT_STYLE
这个项目可选择的设定值有menu, countdown, hidden等等。如果没有设定,预设是menu的意思。这个项目主要是在设定要不要显示菜单!如果你不想要让使用者看到菜单,这里可以设定为countdown。countdown会在屏幕上显示剩余的等待秒数,而hidden则空空如也。
③信息输出的终端机模式:GRUB_TERMINAL_OUTPUT
这个项目是指定输出的画面应该使用哪一个终端机来显示的意思,主要的设定值有『console, serial, gfxterm, vga_text』等等。除非有特别的需求,否则一般使用console即可。
④默认开机菜单项目:GRUB_DEFAULT
这个项目在指定要用哪一个菜单(menuentry)来作为默认开机项目的意思。能使用的设定值包括有『saved,数字,title名,ID名』等。
⑤核心的外加参数功能:GRUB_CMDLINE_LINUX:在这里加入你的核心在启动的时候还需要加入的其它参数。
在修改完成后,直接用grub2-mkconfig来重建grub.cfg即可。
(2)菜单建置的脚本/etc/grub.d/*
这里面的几个文件主要有以下几个:
00_header:主要在建立初始的显示项目,包括需要加载的模块分析、屏幕终端机的格式、倒数秒数、选单是否需要隐藏等等,大部分在/etc/default/grub里面所设定的变量,大会在这个脚本当中被利用来重建grub.cfg。
10_linux:根据分析/boot底下的文件,尝试找到正确的linux核心与读取这个核心需要的文件系统模块与参数等,都在这个脚本运作后找到并设定到grub.cfg当中。因为这个脚本会将所有在/boot底下的每一个核心文件都对应到一个选单,因此核心文件数量越多,你的开机选单项目就越多了。如果未来你不想要旧的核心出现在选单上,那可以透过移除旧核心来处理即可。
30_os-prober:这个脚本默认会到系统上找其他的partition里面可能含有的操作系统,然后将该操作系统做成选单来处理就是了。如果你不想要让其他的操作系统被侦测到并拿来开机,那可以在/etc/default/grub里面加上『GRUB_DISABLE_OS_PROBER=true』取消这个文件的运作。
40_custom:如果你还有其他想要自己手动加上去的选单项目,或者是其他的需求,那么在这里补充。
所以一般来说,我们修改的时候用到的就是40_custom这个文件。我们知道menuentry是一个菜单,那么后续的项目有哪些呢?常见有这几样:
①直接指定核心开机;
②通过chainloader的方式移交loader控制权。
4.initramfs的重要性与新建initramfs文件:dracut/mkinitrd
initramfs内所包含的模块大多是与开机过程有关,而主要以文件系统及硬盘模块(如usb,SCSI等)为主。
一般来说,需要initramfs的时候为:
①根目录所在硬盘为SATA、USB或SCSI等连接接口;
②根目录所在文件系统为LVM、RAID等特殊格式;
③根目录所在文件系统为非传统Linux可识别的文件系统时;
④其他必须要在核心加载时提供的模块。
一般来说,各distribution提供的核心都会附上initramfs文件,但如果你有特殊需要所以想重制initramfs文件的话,可以使用dracut或mkinitrd来处理的。这个文件的处理方式很简单,mandracut或manmkinitrd就知道了。
下面来介绍下dracut功能。
[root@study ~]# dracut [-fv] [–add-drivers 列表] initramfs文件名 核心版本 选项与参数: -f:强迫编译出initramfs,如果initramfs文件已经存在,则覆盖掉旧文件。 -v:显示dracut的运作过程。 –add-drivers列表:在原本的默认核心模块中,增加某些你想要的模块!模块位于核心所在目录/lib/modules/$(uname-r)/kernel/*。 initramfs文件名:就是你需要的文件名。开头最好就是initramfs,后面接版本与功能。 核心版本:预设当然是目前运作中的核心版本,不过你也可以手动输入其他不同版本。 其实dracut还有很多功能,例如底下的几个参数也可以参考看看: –modules:将dracut所提供的开机所需模块(核心模块组)加载,可用模块在底下的目录内/usr/lib/dracut/modules.d/; –gzip|–bzip2|–xz:尝试使用哪一种压缩方式来进行initramfs压缩。预设使用gzip; –filesystems:加入某些额外的文件系统支持。 |
5.测试与安装grub2:grub2-install
加入你的Linux并非使用grub2,那么就需要使用grub-install将一些必要的文件复制到/boot/grub2里面去。
要安装的话,需要这样做:
[root@study ~]# grub2-install [–boot-directory=DIR] INSTALL_DEVICE 选项与参数: –boot-directory=DIR那个DIR为实际的目录,使用grub2-install预设会将grub2所有的档案都复制到/boot/grub2/*,如果想要复制到其他目录与装置去,就得要用这个参数。INSTALL_DEVICE 就是安装的装置代号。 |
最后总结一下:
①如果是从其他bootloader转成grub2时,得先使用grub2-install安装grub2配置文件;
②承上,如果安装到partition时,可能需要加上额外的许多参数才能够顺利安装上去;
③开始编辑/etc/default/grub及/etc/grub.d/*这几个重要的配置文件;
④使用grub2-mkconfig-o/boot/grub2/grub.cfg来建立开机的配置文件。
6.关于开机画面与终端机画面的图形显示方式
如果你想要让你的开机画面使用图形显示方式,例如使用中文来显示你的画面,因为我们预设的locale语系就是zh_CN.utf8嘛!所以理论上grub2会显是中文出来才对啊。有没有办法达成呢?是有的~通过图形显是的方法即可!不过,我们得要重新修改grub.cfg才行喔!依据底下的方式来处理:
# 先改重要的配置文件 [root@study ~]# vim /etc/default/grub …..(前面省略)….. GRUB_TERMINAL=gfxterm # 设定主要的终端机显示为图形界面 GRUB_GFXMODE=1024x768x24 # 图形界面尺寸 GRUB_GFXPAYLOAD_LINUX=keep # 保留图形界面,不要使用text。
# 重新建立配置文件 [root@study ~]# grub2-mkconfig -o /boot/grub2/grub.cfg |
8.为个别菜单加上密码:grub2-mkpasswd-pbkdf2
grub2的菜单管理中,有针对两种身份进行密码设置:
superusers:设定系统管理员与相关参数还有密码等,使用这个密码的用户,将可在grub2内具有所有修改的权限。但一旦设定了这个superusers的参数,则所有的指令修改将会被变成受限制的。
users:设定一般账号的相关参数与密码,可以设定多个用户喔!使用这个密码的用户可以选择要进入某些选单项目。不过,菜单项目也得要搭配相对的账号才行喔!(一般来说,使用这种密码的账号并不能修改菜单的内容,仅能选择进入菜单去开机而已)。
(1)grub2密码设定的文件位置与加密的密码
记得我们在前几小节谈到主要的环境设定是在/etc/grub.d/*里面吧?里面的档案文件名有用数字开头,那些数字照顺序,就是grub.cfg的来源顺序了。因此最早被读的应该是00_header,但是那个档案的内容挺重要的,所以CentOS7不建议你改它~那要改谁?就自己建立一个名为01_users的档案即可!要注意是两个数字开头接着底线的档名才行,然后将账号与密码参数给它补进去。
(2)为个别的菜单设置账号密码的使用模式
现在我们假设在40_custom里面要增加一个可以进入救援模式(rescue)的环境,并且放置到最后一个选单中,同时仅有知道dmtsai的密码者才能够使用,那你应该这样作:
[root@study ~]# vim /etc/grub.d/40_custom …..(前面省略)….. menuentry ‘Rescue CentOS7, with Linux 3.10.0-229.el7.x86_64′ –users dmtsai { load_video set gfxpayload=keep insmod gzio insmod part_gpt insmod xfs set root=’hd0,gpt2′ if [ x$feature_platform_search_hint = xy ]; then search –no-floppy –fs-uuid –set=root –hint=’hd0,gpt2’ 94ac5f77-cb8a-… else search –no-floppy –fs-uuid –set=root 94ac5f77-cb8a-495e-a65b-2ef7442b837c fi linux16 /vmlinuz-3.10.0-229.el7.x86_64 root=/dev/mapper/centos-root ro rd.lvm.lv =centos/root rd.lvm.lv=centos/swap crashkernel=auto rhgb quiet systemd.unit=rescue.target initrd16 /initramfs-3.10.0-229.el7.x86_64.img }
[root@study ~]# grub2-mkconfig -o /boot/grub2/grub.cfg |
最后一步当然不要忘记重建你的grub.cfg啰!然后重新启动测试一下。