boot loader 的两个 stage

在 BIOS 读完信息后,接下来就是会到第一个开机装置 的 MBR 去读取 boot loader 了。这个 boot loader 可以具有选单功能、直接加载核心文件以及控制权 移交的功能等, 系统必须要有 loader 才有办法加载该操作系统的核心就是了。但是我们都知道, MBR 是整个硬盘的第一个 sector 内的一个区块,充其量整个大小也才 446 bytes 而已。我们的 loader 功能这么强,光是程序代码与设 定数据不可能只占这么一点点的容量吧?那如何安装?

为了解决这个问题,所以 Linux 将 boot loader 的程序代码执行与设定值加载分成两个阶段 (stage) 来执行:

  • Stage 1:执行 boot loader 主程序:

第一阶段为执行 boot loader 的主程序,这个主程序必须要被安装在开机区,亦即是 MBR 或者是 boot sector 。但如前所述,因为 MBR 实在太小了,所以,MBR 或 boot sector 通常仅安装 boot loader 的最小 主程序, 并没有安装 loader 的相关配置文件;

  • Stage 2:主程序加载配置文件:

第二阶段为透过 boot loader 加载所有配置文件与相关的环境参数文件 (包括文件系统定义与主要配置文件 grub.cfg), 一般来说,配置文件都在 /boot 底下。

那么这些配置文件是放在哪里啊?这些与 grub2 有关的文件都放置到 /boot/grub2 中,那我们就来看 看有哪些文件吧!

  1. [root@study ~]# ls -l /boot/grub2
  2. -rw-r--r--. device.map <==grub2 的装置对应文件(底下会谈到)
  3. drwxr-xr-x. fonts <==开机过程中的画面会使用到的字型数据
  4. -rw-r--r--. grub.cfg <==grub2 的主配置文件!相当重要!
  5. -rw-r--r--. grubenv <==一些环境区块的符号
  6. drwxr-xr-x. i386-pc <==针对一般 x86 PC 所需要的 grub2 的相关模块
  7. drwxr-xr-x. locale <==就是语系相关的数据啰
  8. drwxr-xr-x. themes <==一些开机主题画面数据
  9. [root@study ~]# ls -l /boot/grub2/i386-pc
  10. -rw-r--r--. acpi.mod <==电源管理有关的模块
  11. -rw-r--r--. ata.mod <==磁盘有关的模块
  12. -rw-r--r--. chain.mod <==进行 loader 控制权移交的相关模块
  13. -rw-r--r--. command.lst <==一些指令相关性的列表
  14. -rw-r--r--. efiemu32.o <==底下几个则是与 uefi BIOS 相关的模块
  15. -rw-r--r--. efiemu64.o
  16. -rw-r--r--. efiemu.mod
  17. -rw-r--r--. ext2.mod <==EXT 文件系统家族相关模块
  18. -rw-r--r--. fat.mod <==FAT 文件系统模块
  19. -rw-r--r--. gcry_sha256.mod <==常见的加密模块
  20. -rw-r--r--. gcry_sha512.mod
  21. -rw-r--r--. iso9660.mod <==光盘文件系统模块
  22. -rw-r--r--. lvm.mod <==LVM 文件系统模块
  23. -rw-r--r--. mdraid09.mod <==软件磁盘阵列模块
  24. -rw-r--r--. minix.mod <==MINIX 相关文件系统模块
  25. -rw-r--r--. msdospart.mod <==一般 MBR 分区表
  26. -rw-r--r--. part_gpt.mod <==GPT 分区表
  27. -rw-r--r--. part_msdos.mod <==MBR 分区表
  28. -rw-r--r--. scsi.mod <==SCSI 相关模块
  29. -rw-r--r--. usb_keyboard.mod <==底下两个为 USB 相关模块
  30. -rw-r--r--. usb.mod
  31. -rw-r--r--. vga.mod <==VGA 显示适配器相关模块
  32. -rw-r--r--. xfs.mod <==XFS 文件系统模块
  33. # 这里只拿一些模块作说明,没有全部的文件都列上来喔!

从上面的说明你可以知道 /boot/grub2/ 目录下最重要的就是配置文件 (grub2.cfg) 以及各种文件系统 的定义! 我们的 loader 读取了这种文件系统定义数据后,就能够认识文件系统并读取在该文件系统 内的核心文件

grub2 的配置文件 /boot/grub2/grub.cfg 初探

grub2 的优点挺多的,包括有:

  • 认识与支持较多的文件系统,并且可以使用 grub2 的主程序直接在文件系统中搜寻核心档名;
  • 开机的时候,可以『自行编辑与修改开机设定项目』,类似 bash 的指令模式;
  • 可以动态搜寻配置文件,而不需要在修改配置文件后重新安装 grub2 。亦即是我们只要修改完/boot/grub2/grub.cfg 里头的设定后,下次开机就生效了!

上面第三点其实就是 Stage 1, Stage 2 分别安装在 MBR (主程序) 与文件系统当中 (配置文件与定义 档) 的原因啦! 好了,接下来,让我们好好了解一下 grub2 的配置文件: /boot/grub2/grub.cfg 这玩 意儿吧!


  • 磁盘与分区槽在 grub2 中的代号

安装在 MBR 的 grub2 主程序,最重要的任务之一就是从磁盘当中加载核心文件, 以让核心能够顺 利的驱动整个系统的硬件。所以啰, grub2 必须要认识硬盘才行啊!那么 grub2 到底是如何认识硬 盘的呢? 嘿嘿! grub2 对硬盘的代号设定与传统的 Linux 磁盘代号可完全是不同的!grub2 对硬盘 的识别使用的是如下的代号:

  1. (hd0,1) # 一般的默认语法,由 grub2 自动判断分区格式
  2. (hd0,msdos1) # 此磁盘的分区为传统的 MBR 模式
  3. (hd0,gpt1) # 此磁盘的分区为 GPT 模式

注意几个东西即可,那就是:

  • 硬盘代号以小括号 ( ) 包起来;
  • 硬盘以 hd 表示,后面会接一组数字;
  • 以『搜寻顺序』做为硬盘的编号!(这个重要!)
  • 第一个搜寻到的硬盘为 0 号,第二个为 1 号,以此类推;
  • 每颗硬盘的第一个 partition 代号为 1 ,依序类推。

所以说,第一颗『搜寻到的硬盘』代号为:『(hd0)』,而该颗硬盘的第一号分区槽为『(hd0,1)』,另外,为了区分不同的分区格式,因此磁盘后面的分区号码可以使用类似 msdos1 与 gpt1 的方式来调整! 最终要记得的是,磁盘的号码是由 0 开始编号,分区槽的号码则与 Linux 一 样,是由 1 号开始编号!

所以说,整个硬盘代号为:

硬盘搜寻顺序 在 Grub2 当中的代号
第一颗(MBR) (hd0) (hd0,msdos1) (hd0,msdos2) (hd0,msdos3)....
第二颗(GPT) (hd1) (hd1,gpt1) (hd1,gpt2) (hd1,gpt3)....
第三颗 (hd2) (hd2,1) (hd2,2) (hd2,3)....

  • /boot/grub2/grub.cfg 配置文件(重点在了解,不要随便改!):

接下来,我们就可以瞧一瞧配置文件的内容了。

  1. [root@study ~]# vim /boot/grub2/grub.cfg
  2. # 开始是 /etc/grub.d/00_header 这个脚本执行的结果展示,主要与基础设定与环境有关
  3. ### BEGIN /etc/grub.d/00_header ###
  4. set pager=1
  5. if [ -s $prefix/grubenv ]; then
  6. load_env
  7. fi
  8. .....(中間省略).....
  9. if [ x$feature_timeout_style = xy ] ; then
  10. set timeout_style=menu
  11. set timeout=5
  12. # Fallback normal timeout code in case the timeout_style feature is
  13. # unavailable.
  14. else
  15. set timeout=5
  16. fi
  17. ### END /etc/grub.d/00_header ###
  18. # 开始执行 /etc/grub.d/10_linux,主要针对实际的 Linux 核心文件的开机环境
  19. ### BEGIN /etc/grub.d/10_linux ###
  20. menuentry 'CentOS Linux 7 (Core), with Linux 3.10.0-229.el7.x86_64' --class rhel fedora \
  21. --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option \
  22. 'gnulinux-3.10.0-229.el7.x86_64-advanced-299bdc5b-de6d-486a-a0d2-375402aaab27' {
  23. load_video
  24. set gfxpayload=keep
  25. insmod gzio
  26. insmod part_gpt
  27. insmod xfs
  28. set root='hd0,gpt2'
  29. if [ x$feature_platform_search_hint = xy ]; then
  30. search --no-floppy --fs-uuid --set=root --hint='hd0,gpt2' 94ac5f77-cb8a-495e-a65b-...
  31. else
  32. search --no-floppy --fs-uuid --set=root 94ac5f77-cb8a-495e-a65b-2ef7442b837c
  33. fi
  34. linux16 /vmlinuz-3.10.0-229.el7.x86_64 root=/dev/mapper/centos-root ro \
  35. rd.lvm.lv=centos/root rd.lvm.lv=centos/swap crashkernel=auto rhgb quiet \
  36. LANG=zh_TW.UTF-8
  37. initrd16 /initramfs-3.10.0-229.el7.x86_64.img
  38. }
  39. ### END /etc/grub.d/10_linux ###
  40. .....(中间省略).....
  41. ### BEGIN /etc/grub.d/30_os-prober ###
  42. ### END /etc/grub.d/30_os-prober ###
  43. ### BEGIN /etc/grub.d/40_custom ###
  44. ### END /etc/grub.d/40_custom ###
  45. .....(底下省略).....

基本上,grub2 不希望你自己修改 grub.cfg 这个配置文件,取而代之的是修改几个特定的配置文件 之后,由 grub2-mkconfig 这个指令来产生新的 grub.cfg 文件。不过,你还是得要了解一下 grub2.cfg 的大致内容。

在 grub.cfg 最开始的部份,其实大多是环境设定与默认值设定等,比较重要的当然是默认由哪个选 项开机 (set default) 以及预设的秒数 (set timeout),再来则是每一个选单的设定,就是在

『 menuentry 』这个设定值之后的项目啰!在鸟哥预设的配置文件当中,其实是有两个 menuentry 的, 也就是说,鸟哥的测试机在开机的时候应该就会有两个可以选择的选单的意思啰!

在 grub.cfg 最开始的部份,其实大多是环境设定与默认值设定等,比较重要的当然是默认由哪个选 项开机 (set default) 以及预设的秒数 (set timeout), 再来则是每一个选单的设定,就是在

『 menuentry 』这个设定值之后的项目啰!在鸟哥预设的配置文件当中,其实是有两个 menuentry 的, 也就是说,鸟哥的测试机在开机的时候应该就会有两个可以选择的选单的意思啰!

在 menuentry 之后会有几个项目的规范,包括『 --class, --unrestricted --id 』等等的指定项目,之后 透过『 { } 』将这个选单会用到的数据框起来, 在选择这个选单之后就会进行括号内的动作的意思。 如果真的点选了这个选单,那 grub2 首先会加载模块,例如上表中的『 load_video, insmod gzio, insmod part_gpt, insmod xfs 』等等的项目, 都是在加载要读取核心文件所需要的磁盘、分区槽、文 件系统、解压缩等等的驱动程序。之后就是三个比较重要的项目:

  • set root='hd0,gpt2'

这 root 是指定 grub2 配置文件所在的那个装置。以我们的测试机来说,当初安装的时候分区出 / 与 /boot 两个装置唷,而 grub2 是在 /boot/grub2 这个位置上,而这个位置的磁盘文件名为 /dev/vda2 ,因此完整 的 grub2 磁盘名称就是 (hd0,2) 啰!因为我们的系统用的是 GTP 的磁盘分区格式, 因此全名就是

『 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 相同,这个档名也是需要搭配『 set root=xxx 』 那个项目的装置, 才会得到正确的位置喔!注意注意!

grub2 配置文件维护 /etc/default/grub 与 /etc/grub.d

grub2 的主配置文件 grub.cfg 因为该文件的内容太过复 杂,数据量非常庞大,grub2 官方说明不建议我们手动修改! 而是应该要透过 /etc/default/grub 这个 主要环境配置文件与 /etc/grub.d/ 目录内的相关配置文件来处理比较妥当!们先来聊聊 /etc/default/grub 这个主要环境配置文件。


  • /etc/default/grub 主要环境配置文件

这个主配置文件的内容大概是长这样:

  1. [root@study ~]# cat /etc/default/grub
  2. [root@study ~]# cat /etc/default/grub
  3. GRUB_TIMEOUT=5 # 指定预设倒数读秒的秒数
  4. GRUB_DEFAULT=saved # 指定预设由哪一个选单来开机,预设开机选单之意
  5. GRUB_DISABLE_SUBMENU=true # 是否要隐藏次选单,通常是藏起来的好
  6. GRUB_TERMINAL_OUTPUT="console" # 指定数据输出的终端机格式,默认是文字终端机
  7. GRUB_CMDLINE_LINUX="rd.lvm.lv=centos/root rd.lvm.lv=centos/swap crashkernel=auto rhgb quiet"
  8. # 就是在 menuentry 括号内的 linux16 项目后续的核心参数
  9. GRUB_DISABLE_RECOVERY="true" # 取消救援选单的制作
  • 倒数时间参数: GRUB_TIMEOUT

这个设定值相当简单,后面就是接你要倒数的秒数即可~例如要等待 30 秒,就在这边改成 『GRUB_TIMEOUT=30』即可!如果不想等待则输入 0 , 如果一定要使用者选择,则填 -1 即可!

  • 是否隐藏选单项目:GRUB_TIMEOUT_STYLE

这个项目可选择的设定值有 menu, countdown, hidden 等等。如果没有设定,预设是 menu 的意思。 这个项目主要是在设定要不要显示选单! 如果你不想要让使用者看到选单,这里可以设定为 countdown!那 countdown 与 hidden 有啥差异呢?countdown 会在屏幕上显示剩余的等待秒数, 而 hidden 则空空如也~

  • 讯息输出的终端机模式:GRUB_TERMINAL_OUTPUT

这个项目是指定输出的画面应该使用哪一个终端机来显示的意思,主要的设定值有『 console, serial,gfxterm, vga_text 』等等。

  • 默认开机选单项目:GRUB_DEFAULT

这个项目在指定要用哪一个选单 (menuentry) 来作为默认开机项目的意思。能使用的设定值包括 有『 saved, 数字, title 名, ID 名』等等。假设你有三笔 menuentry 的项目大约像这样:

  1. menuentry '1st linux system' --id 1st-linux-system { ...}
  2. menuentry '2nd linux system' --id 2nd-linux-system { ...}
  3. menuentry '3rd win system' --id 3rd-win-system { ...}

几个常见的设定值是这样的:

  1. [root@study ~]#
  2. GRUB_DEFAULT=1
  3. 代表使用第二个 menuentry 开机,因为数字的编号是以 0 号开始编的!
  4. GRUB_DEFAULT=3rd-win-system
  5. 代表使用第三个 menuentry 开机,因为里头代表的是 ID 的项目!它会找到 --id 喔!
  6. GRUB_DEFAULT=saved
  7. 代表使用 grub2-set-default 来设定哪一个 menuentry 为默认值的意思。通常预设为 0
  • 核心的外加参数功能:GRUB_CMDLINE_LINUX

如果你的核心在启动的时候还需要加入额外的参数,就在这里加入吧!举例来说,如果你除了预 设的核心参数之外,还需要让你的磁盘读写机制为 deadline 这个机制时, 可以这样处理:

  1. GRUB_CMDLINE_LINUX="..... crashkernel=auto rhgb quiet

这个主要环境配置文件编写完毕之后,必须要使用 grub2-mkconfig 来重建 grub.cfg 才行喔!因为主 配置文件就是 grub.cfg 而已, 我们是透过许多脚本的协力来完成 grub.cfg 的自动建置。当然啰, 额外自己设定的项目,就是写入 /etc/default/grub 文件内就是了。


  • 选单建置的脚本 /etc/grub.d/*

grub2-mkconfig 会去分析 /etc/grub.d/* 里面的文件,然后执行该文件来建置 grub.cfg 所以啰, /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 的功能啦!常见的有这几样:

  • 直接指定核心开机

基本上如果是 Linux 的核心要直接被用来开机,那么你应该要透过 grub2-mkconfig 去抓 10_linux 这个脚本直接制作即可,基本上如果是 Linux 的核心要直接被用来开机,那么你应该要透过 grub2-mkconfig 去抓 10_linux 这个脚本直接制作即可,因此这个部份你不太需要记忆! 因为在 grub.cfg 当中就已经 是系统能够捉到的正确的核心开机选单了!不过如果你有比较特别的参数需要进行呢?这时候你 可以这样作: (1)先到 grub.cfg 当中取得你要制作的那个核心的选单项目,然后将它复制到 40_custom 当中 (2)再到 40_custom 当中依据你的需求修改即可。

  • 透过 chainloader 的方式移交 loader 控制权

所谓的 chain loader (开机管理程序的链结) 仅是在将控制权交给下一个 boot loader 而已, 所以 grub2 并不需要认识与找出 kernel 的檔名 ,『 他只是将 boot 的控制权交给下一个 boot sector 或 MBR 内的 boot loader 而已 』 所以通常他也不需要去查验下一个 boot loader 的文件系统!

一般来说, chain loader 的设定只要两个就够了,一个是预计要前往的 boot sector 所在的分区槽 代号, 另一个则是设定 chainloader 在那个分区槽的 boot sector (第一个扇区) 上!假设我的 Windows 分区槽在 /dev/sda1 ,且我又只有一颗硬盘,那么要 grub 将控制权交给 windows 的 loader 只要这样就够了:

  1. menuentry "Windows" {
  2. insmod chain # 你得要先加载 chainloader 的模块对吧?
  3. insmod ntfs # 建议加入 windows 所在的文件系统模块较佳!
  4. set root=(hd0,1) # 是在哪一个分区槽~最重要的项目!
  5. chainloader +1 # 请去 boot sector 将 loader 软件读出来的意思!
  6. }

initramfs 的重要性与建立新 initramfs 文件

initramfs 他的目 的在于提供开机过程中所需要的最重要核心模块,以让系统开机过程可以顺利完成。 会需要 initramfs 的原因,是因为核心模块放置于 /lib/modules/$(uname -r)/kernel/ 当中, 这些模块必须要根 目录 (/) 被挂载时才能够被读取。但是如果核心本身不具备磁盘的驱动程序时,当然无法挂载根目录,也就没有办法取得驱动程序,因此造成两难的地步。

initramfs 可以将 /lib/modules/.... 内的『开机过程当中一定需要的模块』包成一个文件 (檔名就是 initramfs), 然后在开机时透过主机的 INT 13 硬件功能将该文件读出来解压缩,并且 initramfs 在内 存内会仿真成为根目录, 由于此虚拟文件系统 (Initial RAM Disk) 主要包含磁盘与文件系统的模块, 因此我们的核心最后就能够认识实际的磁盘, 那就能够进行实际根目录的挂载啦!所以说:『initramfs 内所包含的模块大多是与开机过程有关,而主要以文件系统及硬盘模块 (如 usb, SCSI 等) 为主』

一般来说,需要 initramfs 的时刻为:

  • 根目录所在磁盘为 SATA、USB 或 SCSI 等连接接口;
  • 根目录所在文件系统为 LVM, RAID 等特殊格式;
  • 根目录所在文件系统为非传统 Linux 认识的文件系统时;
  • 其他必须要在核心加载时提供的模块。

一般来说,各 distribution 提供的核心都会附上 initramfs 文件,但如果妳有特殊需要所以想重制 initramfs 文件的话, 可以使用 dracut / mkinitrd 来处理的。这个文件的处理方式很简单, man dracut 或 man mkinitrd 就知道了。 CentOS 7 应该要使用 dracut 才对,不过 mkinitrd 还是有保留 下来,两者随便你玩!鸟哥这里主要是介绍 dracut 就是了!

  1. [root@study ~]# dracut [-fv] [--add-drivers 列表] initramfs 檔名 核心版本
  2. 选项与参数:
  3. -f :强迫编译出 initramfs ,如果 initramfs 文件已经存在,则覆盖掉旧文件
  4. -v :显示 dracut 的运作过程
  5. --add-drivers 列表:在原本的默认核心模块中,增加某些你想要的模块!模块位于核心所在目录 /lib/modules/$(uname -r)/kernel/*
  6. initramfs 檔名 :就是你需要的檔名!开头最好就是 initramfs,后面接版本与功能
  7. 核心版本 :预设当然是目前运作中的核心版本,不过你也可以手动输入其他不同版本!
  8. 其实 dracut 还有很多功能,例如底下的几个参数也可以参考看看:
  9. --modules :将 dracut 所提供的开机所需模块 (核心核模块) 加载,可用模块在底下的目录内 /usr/lib/dracut/modules.d/
  10. --gzip|--bzip2|--xz:尝试使用哪一种压缩方式来进行 initramfs 压缩。预设使用 gzip 喔!
  11. --filesystems :加入某些额外的文件系统支持!
  12. 范例一:以 dracut 的默认功能建立一个 initramfs 虚拟磁盘文件
  13. [root@study ~]# dracut -v initramfs-test.img $(uname -r)
  14. Executing: /sbin/dracut -v initramfs-test.img 3.10.0-229.el7.x86_64
  15. *** Including module: bash *** # 先加载 dracut 本身的模块支持
  16. *** Including module: nss-softokn ***
  17. *** Including modules done ***
  18. .....(中間省略)..... # 底下两行在处理核心模块
  19. *** Installing kernel module dependencies and firmware ***
  20. *** Installing kernel module dependencies and firmware done ***
  21. .....(中間省略).....
  22. *** Generating early-microcode cpio image *** # 建立微指令集
  23. *** Constructing GenuineIntel.bin ****
  24. *** Store current command line parameters ***
  25. *** Creating image file *** # 开始建立 initramfs 啰!
  26. *** Creating image file done ***
  27. 范例二:额外加入 e1000e 网卡驱动与 ext4/nfs 文件系统在新的 initramfs 内
  28. [root@study ~]# dracut -v --add-drivers "e1000e" --filesystems "ext4 nfs" \
  29. > initramfs-new.img $(uname -r)
  30. [root@study ~]# lsinitrd initramfs-new.img | grep -E '(e1000|ext4|nfs)'
  31. usr/lib/modules/3.10.0-229.el7.x86_64/kernel/drivers/net/ethernet/intel/e1000e
  32. usr/lib/modules/3.10.0-229.el7.x86_64/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko
  33. usr/lib/modules/3.10.0-229.el7.x86_64/kernel/fs/ext4
  34. usr/lib/modules/3.10.0-229.el7.x86_64/kernel/fs/ext4/ext4.ko
  35. usr/lib/modules/3.10.0-229.el7.x86_64/kernel/fs/nfs
  36. usr/lib/modules/3.10.0-229.el7.x86_64/kernel/fs/nfs/nfs.ko
  37. # 你可以看得到,新增的模块现在正在新的 initramfs 当中了呢!很愉快喔!

测试与安装 grub2

如果你的 Linux 主机本来就是使用 grub2 作为 loader 的话,那么你就不需要重新安装 grub2 了, 因为 grub2 本来就会主动去读取配置文件!首先,你必须要使用 grub-install 将一些必要的文件复制到 /boot/grub2 里面去,你应该这样做的:

  1. [root@study ~]# grub2-install [--boot-directory=DIR] INSTALL_DEVICE
  2. 选项与参数:
  3. --boot-directory=DIR 那个 DIR 为实际的目录,使用 grub2-install 预设会将
  4. grub2 所有的文件都复制到 /boot/grub2/* ,如果想要复制到其他目录与装置去,
  5. 就得要用这个参数。
  6. INSTALL_DEVICE 安装的装置代号啦!
  7. 范例一:将 grub2 安装在目前系统的 MBR 底下,我的系统为 /dev/vda:
  8. [root@study ~]# grub2-install /dev/vda
  9. # 因为原本 /dev/vda 就是使用 grub2 ,所以似乎不会出现什么特别的讯息。
  10. # 如果去查阅一下 /boot/grub2 的内容,会发现所有的文件都更新了,因为我们重装了!
  11. # 但是注意到,我们并没有配置文件喔!那要自己建立!

基本上,grub2-install 大概仅能安装 grub2 主程序与相关软件到 /boot/grub2/ 那个目录去, 如果后面 的装置填的是整个系统 (/dev/vda, /dev/sda...), 那 loader 的程序才会写入到 MBR 里面去。如果是 XFS 文件系统的 /dev/vda2 装置的话 (个别 partition),那 grub2-install 就会告诉你, 该文件系统并 不支持 grub2 的安装喔!也就是你不能用 grub2-install 将你的主程序写入到 boot sector 里头去的意思啦!

  1. # 尝试看一下你的系统中有没有其他的 xfs 文件系统,且为传统的 partition 类型?
  2. [root@study ~]# df -T |grep -i xfs
  3. /dev/mapper/centos-root xfs 10475520 4128728 6346792 40% /
  4. /dev/mapper/centos-home xfs 5232640 665544 4567096 13% /home
  5. /dev/mapper/raidvg-raidlv xfs 1558528 33056 1525472 3% /srv/raidlvm
  6. /dev/vda2 xfs 1038336 144152 894184 14% /boot
  7. /dev/vda4 xfs 1038336 63088 975248 7% /srv/myproject
  8. # 看起来仅有 /dev/vda4 比较适合做个练习的模样了!来瞧瞧先!
  9. # 将 grub2 的主程序安装到 /dev/vda4 去看看!
  10. [root@study ~]# grub2-install /dev/vda4
  11. Installing for i386-pc platform.
  12. grub2-install: error: hostdisk//dev/vda appears to contain a xfs filesystem which isn't
  13. known to reserve space for DOS-style boot. Installing GRUB there could result in
  14. FILESYSTEM DESTRUCTION if valuable data is overwritten by grub-setup (--skip-fs-probe
  15. disables this check, use at your own risk).
  16. # 说是 xfs 恐怕不能支持你的 boot sector 概念!这个应该是误判!所以我们还是给它强制装一下!
  17. root@study ~]# grub2-install --skip-fs-probe /dev/vda4
  18. Installing for i386-pc platform.
  19. grub2-install: warning: File system xfs doesn't support embedding.
  20. grub2-install: warning: Embedding is not possible. GRUB can only be installed in this
  21. setup by using blocklists. However, blocklists are UNRELIABLE and their use is
  22. discouraged..
  23. grub2-install: error: will not proceed with blocklists.
  24. # 还是失败!因为还是担心 xfs 被搞死~好!没问题!加个 --force 与 --recheck 重新处理一遍!
  25. [root@study ~]# grub2-install --force --recheck --skip-fs-probe /dev/vda4
  26. Installing for i386-pc platform.
  27. grub2-install: warning: File system ‘xfs’ doesn't support embedding.
  28. grub2-install: warning: Embedding is not possible. GRUB can only be installed in this
  29. setup by using blocklists. However, blocklists are UNRELIABLE and their use is
  30. discouraged..
  31. Installation finished. No error reported.
  32. # 注意看!原本是无法安装的错误,现在仅有 warning 警告讯息,所以这样就安装到 partition 上了!

上面这样就将 grub2 的主程序安装到 /dev/vda4 以及重新安装到 MBR 里面去了。现在来思考一下, 我们知道 grub2 主程序会去找 grub.cfg 这个文件,大多是在 /boot/grub2/grub.cfg 里面,那有趣了, 我们的 MBR 与 /dev/vda4 都是到 /boot/grub2/grub.cfg 去抓设定吗? 如果是多重操作系统那怎办? 呵呵!这就需要重新进入新系统才能够安装啦!

最后总结一下:

  1. 如果是从其他 boot loader 转成 grub2 时,得先使用 grub2-install 安装 grub2 配置文件;
  2. 承上,如果安装到 partition 时,可能需要加上额外的许多参数才能够顺利安装上去!
  3. 开始编辑 /etc/default/grub 及 /etc/grub.d/* 这几个重要的配置文件;
  4. 使用 grub2-mkconfig -o /boot/grub2/grub.cfg 来建立开机的配置文件!

关于开机画面与终端机画面的图形显示方式

如果你想要让你的开机画面使用图形显示方式,例如使用中文来显示你的画面啊!因为我们预设的 locale 语系就是 zh_TW.utf8 嘛! 所以理论上 grub2 会显是中文出来才对啊!有没有办法达成呢? 是有的~透过图形显是的方法即可!不过, 我们得要重新修改 grub.cfg 才行喔!依据底下的方式来 处理:

  1. # 先改重要的配置文件
  2. [root@study ~]# vim /etc/default/grub
  3. .....(前面省略).....
  4. GRUB_TERMINAL=gfxterm # 设定主要的终端机显示为图形界面!
  5. GRUB_GFXMODE=1024x768x24 # 图形界面的 X, Y, 彩度资料
  6. GRUB_GFXPAYLOAD_LINUX=keep # 保留图形界面,不要使用 text 喔!
  7. # 重新建立配置文件
  8. [root@study ~]# grub2-mkconfig -o /boot/grub2/grub.cfg

为个别选单加上密码

grub2 控制有:(1)grub2 的选单指令列修改与 (2)进入选择的选单开机流程。


  • grub2 的账号、密码与选单设定

grub2 有点在模拟 Linux 的账号管理方案喔!因为在 grub2 的选单管理中,有针对两种身份进行密 码设定:

  • superusers: 设定系统管理员与相关参数还有密码等,使用这个密码的用户,将可在 grub2 内具有所有修 改的权限。 但一旦设定了这个 superusers 的参数,则所有的指令修改将会被变成受限制的!

  • users: 设定一般账号的相关参数与密码,可以设定多个用户喔!使用这个密码的用户可以选择要进入某些 选单项目。 不过,选单项目也得要搭配相对的账号才行喔!(一般来说,使用这种密码的账号并不能修改选 单的内容,仅能选择进入选单去开机而已)

这样说可能你不是很容易看得懂,我们使用底下的一个范例来说明你就知道怎么处理了。另外,底下 的范例是单纯给读者们看看而已的~ 不能够直接用在我们的测试机器里面喔!

假设你的系统有三个各别的操作系统,分别安装在 (hd0,1), (hd0,2), (hd0,3) 当中。假设 (hd0,1) 是所有人都可以选 择进入的系统, (hd0,2) 是只有系统管理员可以进入的系统,(hd0,3)则是另一个一般用户与系统管理员可以进入的 系统。另外,假设系统管理员的账号/密码设定为 vbird/abcd1234, 而一般账号为 dmtsai/dcba4321 ,那该如何设 定?

  1. # 第一个部份是先设定好管理员与一般账号的账号名称与密码项目!
  2. set superusers="vbird" # 这里是设定系统管理员的账号名称为啥的意思!
  3. password vbird abcd1234 # 当然要给予这个账号密码啊!
  4. password dmtsai dcba4321 # 没有输入 superuses 的其他账号,当然就是判定为一般账号
  5. menuentry "大家都可以选择我来开机喔!" --unrestricted {
  6. set root=(hd0,1)
  7. chainloader +1
  8. }
  9. menuentry "只有管理员的密码才有办法使用" --users "" {
  10. set root=(hd0,2)
  11. chainloader +1
  12. }
  13. menuentry "只有管理员与 dmtsai 才有办法使用喔!" --users dmtsai {
  14. set root=(hd0,3)
  15. chainloader +1
  16. }

如上表所示,你得要使用 superuses 来指定哪个账号是管理员!另外,这个账号与 Linux 的实体账 号无关,这仅是用来判断密码所代表的意义而已。 而密码的给予有两种语法:

  • password_pbkdf2 账号 『使用 grub2-mkpasswd-pbkdf2 所产生的密码』
  • password 账号 『没加密的明码』

有了账号与密码之后,在来就是在个别的选单上面加上是否要取消限制 (--unrestricted) 或者是给予哪 个用户 (--users) 的设定项目。 同时请注意喔,所有的系统管理员所属的密码应该是能够修改所有的 选单,因此你无须在第三个选单上面加入 vbird 这个管理员账号!


  • grub2 密码设定的文件位置与加密的密码

还记得我们在前几小节谈到主要的环境设定是在 /etc/grub.d/* 里面吧?里面的文件文件名有用数字开头,那些数字照顺序,就是 grub.cfg 的来源顺序了。 因此最早被读的应该是 00_header,但是那 个文件的内容挺重要的,所以 CentOS 7 不建议你改它~那要改谁?就自己建立一个名为 01_users的文件即可! 要注意是两个数字开头接着底线的档名才行喔!然后将账号与密码参数给它补进去!

现在让我们将 vbird 与 dmtsai 的密码加密,实际在我们的测试机器上面建置起来吧

  1. # 1. 先取得 vbird 与 dmtsai 的密码。底下我仅以 vbird 来说明而已!
  2. [root@study ~]# grub2-mkpasswd-pbkdf2
  3. Enter password: # 这里输入你的密码
  4. Reenter password: # 再一次输入密码
  5. PBKDF2 hash of your password is grub.pbkdf2.sha512.10000.9A2EBF7A1F484...
  6. # 上面特殊字体从 grub.pbkdf2.... 的那一行,全部的数据就是你的密码喔!复制下来!
  7. # 2. 将密码与账号写入到 01_users 文件内
  8. [root@study ~]# vim /etc/grub.d/01_users
  9. cat << eof
  10. set superusers="vbird"
  11. password_pbkdf2 vbird grub.pbkdf2.sha512.10000.9A2EBF7A1F484904FF3681F97AE22D58DFBFE65A...
  12. password_pbkdf2 dmtsai grub.pbkdf2.sha512.10000.B59584C33BC12F3C9DB8B18BE9F557631473AED...
  13. eof
  14. # 请特别注意,在 /etc/grub.d/* 底下的文件是『执行脚本』档,是要被执行的!
  15. # 因此不能直接写帐密,而是透过 cat 或 echo 等指令方式来将帐密数据显示出来才行喔!
  16. # 3. 因为 /etc/grub.d/ 底下应该是执行档,所以刚刚建立的 01_users 当然要给予执行权限
  17. [root@study ~]# chmod a+x /etc/grub.d/01_users
  18. [root@study ~]# ll /etc/grub.d/01_users
  19. -rwxr-xr-x. 1 root root 649 Aug 31 19:42 /etc/grub.d/01_users

  • 为个别的选单设定账号密码的使用模式

回想一下我们之前的设定,目前测试机器的 Linux 系统选单应该有五个:

  • 来自 /etc/grub.d/10_linux 这个文件主动侦测的两个 menuentry;

  • 来自 /etc/grub.d/40_custom 这个我们自己设定的三个 menuentry

在 40_custom 内的设定,我们可以针对每个 menuentry 去调整,而且该调整是固定的,不会随便被 更改。至于 10_linux 文件中, 则每个 menuentry 的设定都会依据 10_linux 的数据去变更,也就是 由 10_linux 侦测到的核心开机选单都会是相同的意思。

因为我们已经在 01_users 文件内设定了 set superusers="vbird" 这个设定值,因此每个选单内的参数 除了知道 vbird 密码的人之外, 已经不能随便修改了喔!所以,选择 10_linux 制作出来的选单开 机,应该就算正常开机,所以,我们默认不要使用密码好了! 刚刚好 10_linux 的 menuentry 设定值就是这样:

  1. [root@study ~]# vim /etc/grub.d/10_linux
  2. .....(前面省略).....
  3. CLASS="--class gnu-linux --class gnu --class os --unrestricted"
  4. # 这一行大约在 29 行左右,你可以利用 unrestricted 去搜寻即可!
  5. # 预设已经不受限制 (--unrestricted) 了!如果想要受限制,在这里将 --unrestricted
  6. # 改成你要使用的 --users "账号名称" 即可!不过,还是不建议修改啦!

现在我们假设在 40_custom 里面要增加一个可以进入救援模式 (rescue) 的环境,并且放置到最后一 个选单中,同时仅有知道 dmtsai 的密码者才能够使用, 那你应该这样作:

  1. [root@study ~]# vim /etc/grub.d/40_custom
  2. .....(前面省略).....
  3. menuentry 'Rescue CentOS7, with Linux 3.10.0-229.el7.x86_64' --users dmtsai {
  4. load_video
  5. set gfxpayload=keep
  6. insmod gzio
  7. insmod part_gpt
  8. insmod xfs
  9. set root='hd0,gpt2'
  10. if [ x$feature_platform_search_hint = xy ]; then
  11. search --no-floppy --fs-uuid --set=root --hint='hd0,gpt2' 94ac5f77-cb8a-...
  12. else
  13. search --no-floppy --fs-uuid --set=root 94ac5f77-cb8a-495e-a65b-2ef7442b837c
  14. fi
  15. linux16 /vmlinuz-3.10.0-229.el7.x86_64 root=/dev/mapper/centos-root ro rd.lvm.lv
  16. =centos/root rd.lvm.lv=centos/swap crashkernel=auto rhgb quiet
  17. systemd.unit=rescue.target
  18. initrd16 /initramfs-3.10.0-229.el7.x86_64.img
  19. }
  20. [root@study ~]# grub2-mkconfig -o /boot/grub2/grub.cfg

Linux学习-Boot Loader: Grub2的更多相关文章

  1. linux学习书籍推荐《鸟哥的Linux私房菜》下载

    下载地址:点我 <鸟哥的Linux私房菜:基础学习篇>是具有知名度的Linux入门书<鸟哥的Linux私房菜基础学习篇>的最新版,全面而详细地介绍了Linux操作系统.< ...

  2. boot loader:grub入门[转]

    Boot Loader: Grub 在看完了前面的整个启动流程,以及核心模块的整理之后,你应该会发现到一件事情, 那就是『 boot loader 是加载核心的重要工具』啊!没有 boot loade ...

  3. LM3S之boot loader学习笔记-2

    LM3S之boot loader学习笔记-2 彭会锋 () 上一篇中介绍了bootloader的基础知识,对于bootloader的作用和如何编写bootloader也有了大概的了解了,这一篇主要讲解 ...

  4. LM3S之boot loader学习笔记-1

    LM3S之boot loader学习笔记-1 彭会锋 (首先声明,此系列文章编写参考了很多资料,其中一些内容是原版内容的引用和整理,并加入了一些自己的见解,我已经尽量标明引用部分,如有未全部标注部分, ...

  5. MIT 6.828 JOS学习笔记7. Lab 1 Part 2.2: The Boot Loader

    Lab 1 Part 2 The Boot Loader Loading the Kernel 我们现在可以进一步的讨论一下boot loader中的C语言的部分,即boot/main.c.但是在我们 ...

  6. MIT 6.828 JOS学习笔记4. Lab 1 Part 2.1: The Boot Loader

    Part 2: The Boot Loader 对于PC来说,软盘,硬盘都可以被划分为一个个大小为512字节的区域,叫做扇区.一个扇区是一次磁盘操作的最小粒度.每一次读取或者写入操作都必须是一个或多个 ...

  7. MIT JOS学习笔记01:环境配置、Boot Loader(2016.10.22)

    未经许可谢绝以任何形式对本文内容进行转载! 一.环境配置 关于MIT课程中使用的JOS的配置教程网上已经有很多了,在这里就不做介绍,个人使用的是Ubuntu 16.04 + qemu.另注,本文章中贴 ...

  8. 《xv6 Appendices: PC Hardware and Boot loader》学习笔记

    MIT 6.828 Lecture 2的preparation要求阅读<xv6 book>的附录部分,附录包括"PC Hardware"和"The Boot ...

  9. 【Linux】Linux学习笔记(完结)

    前言 在工作中发现Linux系统的重要性,于是计划重温下Linux,顺便记录笔记方便之后查阅. 磁盘分区 在Linux系统中,每个设备都被当成一个文件来对待:如IDE接口的硬盘文件名为/dev/hd[ ...

随机推荐

  1. Java 8特性尝鲜:新新IO

    Java 8特性尝鲜:新新IO 在这个专题前面的文章中,我们已经看到,使用Java8的lambda表达式对现有的JDK1.2 I/O库的提升,主要是可以使用lambda表达式来构造java.io.Fi ...

  2. @ConfigurationProperties

    功能 将属性文件与一个Java类绑定,属性文件中的变量与Java类中的成员变量一一对应,无需完全一致. 如需将 @ConfigurationProperties 注解的目标类添加到Spring IOC ...

  3. Spring Cloud--搭建Eureka注册中心服务

    使用RestTemplate远程调用服务的弊端: Eureka注册中心: Eureka原理: 搭建Eureka服务 引pom 启动类: 启动类上要加上@EnableEurekaServer注解: 配置 ...

  4. 邮箱/邮件地址的正则表达式及分析(JavaScript,email,regex)

    简言 在做用户注册时,常会用到邮箱/邮件地址的正则表达式.本文列举了几种方案,大家可以根据自己的项目情况,选择最适合的方案. 方案1 (常用) 规则定义如下: 以大写字母[A-Z].小写字母[a-z] ...

  5. robotframework介绍

    1.测试用例使用文本文件(TXT或者TSV文件)保存,使用制表符分隔数据.可以方便的使用任何文本编辑器,或者EXCEL编辑测试用例.也可以使用HTML格式创建用例.2.测试用例中支持变量使用,可以使用 ...

  6. Codeforces Round #320 (Div. 1) [Bayan Thanks-Round] A A Problem about Polyline(数学)

    题目中给出的函数具有周期性,总可以移动到第一个周期内,当然,a<b则无解. 假设移动后在上升的那段,则有a-2*x*n=b,注意限制条件x≥b,n是整数,则n≤(a-b)/(2*b).满足条件的 ...

  7. HDU 4738 Caocao's Bridges taijan (求割边,神坑)

    神坑题.这题的坑点有1.判断连通,2.有重边,3.至少要有一个人背*** 因为有重边,tarjan的时候不能用子结点和父节点来判断是不是树边的二次访问,所以我的采用用前向星存边编号的奇偶性关系,用^1 ...

  8. Android(java)学习笔记116:BroadcastReceiver之 静态注册 和 动态注册

    1. 广播接受者>什么是广播.收音机.电台:对外发送信号.收音机:接收电台的信号. >在android系统里面,系统有很多重要的事件: 电池电量低,插入充电器,sd卡被移除,有电话打出去, ...

  9. idea中pom.xml没有工作 IDEA中maven项目pom.xml依赖不生效解决

    问题: 今天在web项目中需要引入poi相关jar包.查看之下才发现pom.xml中的依赖虽然已经下载到了本地仓库 repository,但是却没有加入到项目路径的 Extenal Libraries ...

  10. SSH程序框架之Spring与HIbernate整合

    spring整合hibernate 有两种方式 1.注解方式 2.xml方式实现 Spring整合Hibernate有什么好处? 1.由IOC容器来管理Hibernate的SessionFactory ...