因为MBR(MBR 是整个硬盘的第一个 sector 内的一个区块,大小只有446 Bytes)和GPT(GPT 也没有很大的扇区来储存 loader 的数据)的容量不足,所以Linux 将 boot loader 的程序码执行与设置值载入分成两个阶段 (stage) 来执行:

  1. 执行 boot loader 主程序: 第一阶段为执行 boot loader 的主程序,这个主程序必须要被安装在开机区,亦即是 MBR 或者是 boot sector 。
  2. 主程序载入配置文件: 第二阶段为通过 boot loader 载入所有配置文件与相关的环境参数文件 (包括文件系统定义与主要配置文件 grub.cfg), 一般来说,配置文件都在 /boot 下面。
# ll /boot/grub2
total 32
-rw-r--r--. 1 root root   64 Oct 23 01:13 device.map   #grub2 的设备对应档
drwxr-xr-x. 2 root root   25 Oct 23 01:13 fonts   #开机过程中的画面会使用到的字体数据
-rw-r--r--. 1 root root 4306 Nov 13 10:22 grub.cfg   #grub2 的主配置文件
-rw-r--r--. 1 root root 1024 Nov 13 10:22 grubenv   #环境区块的符号
drwxr-xr-x. 2 root root 8192 Oct 23 01:13 i386-pc   #针对一般 x86 PC 所需要的 grub2 的相关模块
drwxr-xr-x. 2 root root 4096 Oct 23 01:13 locale   #语系相关的数据


# ls -l /boot/grub2/i386-pc
-rw-r--r--.  acpi.mod              #电源管理有关的模块
-rw-r--r--.  ata.mod               #磁盘有关的模块
-rw-r--r--.  chain.mod             #进行 loader 控制权移交的相关模块
-rw-r--r--.  command.lst           #一些指令相关性的列表
-rw-r--r--.  efiemu32.o            #下面几个则是与 uefi BIOS 相关的模块
-rw-r--r--.  efiemu64.o
-rw-r--r--.  efiemu.mod
-rw-r--r--.  ext2.mod              #EXT 文件系统家族相关模块
-rw-r--r--.  fat.mod               #FAT 文件系统模块
-rw-r--r--.  gcry_sha256.mod       #常见的加密模块
-rw-r--r--.  gcry_sha512.mod
-rw-r--r--.  iso9660.mod           #光盘文件系统模块
-rw-r--r--.  lvm.mod               #LVM 文件系统模块
-rw-r--r--.  mdraid09.mod          #软件磁盘阵列模块
-rw-r--r--.  minix.mod             #MINIX 相关文件系统模块
-rw-r--r--.  msdospart.mod         #一般 MBR 分区表
-rw-r--r--.  part_gpt.mod          #GPT 分区表
-rw-r--r--.  part_msdos.mod        #MBR 分区表
-rw-r--r--.  scsi.mod              #SCSI 相关模块
-rw-r--r--.  usb_keyboard.mod      #下面两个为 USB 相关模块
-rw-r--r--.  usb.mod
-rw-r--r--.  vga.mod               #VGA 显卡相关模块
-rw-r--r--.  xfs.mod               #XFS 文件系统模块
......

上面查询的结构就是grub2的配置文件以及各种文件系统的定义,loader读取了这些配置后,就能够认识文件系统并读取在该文件系统内的核心文件。

grub2的优点

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

磁盘与分区在 grub2 中的代号

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

硬盘代号特点:

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

由于 BIOS 可以调整磁盘的开机顺序,因此磁盘对应的 (hdN) 那个号码 N 是会变动的

/boot/grub2/grub.cfg 配置文件

# cat /boot/grub2/grub.cfg
#
# DO NOT EDIT THIS FILE
#
# It is automatically generated by grub2-mkconfig using templates
# from /etc/grub.d and settings from /etc/default/grub
#


开始是 /etc/grub.d/00_header 这个脚本执行的结果展示,主要与基础设置与环境有关

### BEGIN /etc/grub.d/00_header ###
set pager=1

if [ -s $prefix/grubenv ]; then
  load_env
fi
if [ "${next_entry}" ] ; then
   set default="${next_entry}"
   set next_entry=
   save_env next_entry
   set boot_once=true
else
   set default="${saved_entry}"
fi

if [ x"${feature_menuentry_id}" = xy ]; then
  menuentry_id_option="--id"
else
  menuentry_id_option=""
fi

export menuentry_id_option

if [ "${prev_saved_entry}" ]; then
  set saved_entry="${prev_saved_entry}"
  save_env saved_entry
  set prev_saved_entry=
  save_env prev_saved_entry
  set boot_once=true
fi

function savedefault {
  if [ -z "${boot_once}" ]; then
    saved_entry="${chosen}"
    save_env saved_entry
  fi
}

function load_video {
  if [ x$feature_all_video_module = xy ]; then
    insmod all_video
  else
    insmod efi_gop
    insmod efi_uga
    insmod ieee1275_fb
    insmod vbe
    insmod vga
    insmod video_bochs
    insmod video_cirrus
  fi
}

terminal_output console
if [ x$feature_timeout_style = xy ] ; then
  set timeout_style=menu
  set timeout=5
# Fallback normal timeout code in case the timeout_style feature is
# unavailable.
else
  set timeout=5
fi
### END /etc/grub.d/00_header ###

### BEGIN /etc/grub.d/00_tuned ###
set tuned_params=""
set tuned_initrd=""
### END /etc/grub.d/00_tuned ###

### BEGIN /etc/grub.d/01_users ###
if [ -f ${prefix}/user.cfg ]; then
  source ${prefix}/user.cfg
  if [ -n "${GRUB2_PASSWORD}" ]; then
    set superusers="root"
    export superusers
    password_pbkdf2 root ${GRUB2_PASSWORD}
  fi
fi
### END /etc/grub.d/01_users ###

开始执行 /etc/grub.d/10_linux,主要针对实际的 Linux 核心文件的开机环境
### BEGIN /etc/grub.d/10_linux ###
menuentry 'CentOS Linux (3.10.0-1160.45.1.el7.x86_64) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-1160.el7.x86_64-advanced-08266a18-3bde-41bc-991b-afcf57578966' {
	load_video
	set gfxpayload=keep
	insmod gzio
	insmod part_msdos
	insmod xfs
	set root='hd0,msdos1'
	if [ x$feature_platform_search_hint = xy ]; then
	  search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1'  a2bb0196-8c99-437d-b189-162a79cf17c5
	else
	  search --no-floppy --fs-uuid --set=root a2bb0196-8c99-437d-b189-162a79cf17c5
	fi
	linux16 /vmlinuz-3.10.0-1160.45.1.el7.x86_64 root=/dev/mapper/centos-root ro crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet LANG=en_US.UTF-8
	initrd16 /initramfs-3.10.0-1160.45.1.el7.x86_64.img
}
menuentry 'CentOS Linux (0-rescue-7736398a16282141bc37306fb9eb32e5) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-0-rescue-7736398a16282141bc37306fb9eb32e5-advanced-08266a18-3bde-41bc-991b-afcf57578966' {
	load_video
	insmod gzio
	insmod part_msdos
	insmod xfs
	set root='hd0,msdos1'
	if [ x$feature_platform_search_hint = xy ]; then
	  search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1'  a2bb0196-8c99-437d-b189-162a79cf17c5
	else
	  search --no-floppy --fs-uuid --set=root a2bb0196-8c99-437d-b189-162a79cf17c5
	fi
	linux16 /vmlinuz-0-rescue-7736398a16282141bc37306fb9eb32e5 root=/dev/mapper/centos-root ro crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet
	initrd16 /initramfs-0-rescue-7736398a16282141bc37306fb9eb32e5.img
}

### END /etc/grub.d/10_linux ###

### BEGIN /etc/grub.d/20_linux_xen ###
### END /etc/grub.d/20_linux_xen ###

### BEGIN /etc/grub.d/20_ppc_terminfo ###
### END /etc/grub.d/20_ppc_terminfo ###

### BEGIN /etc/grub.d/30_os-prober ###
### END /etc/grub.d/30_os-prober ###

### BEGIN /etc/grub.d/40_custom ###
# This file provides an easy way to add custom menu entries.  Simply type the
# menu entries you want to add after this comment.  Be careful not to change
# the 'exec tail' line above.
### END /etc/grub.d/40_custom ###

### BEGIN /etc/grub.d/41_custom ###
if [ -f  ${config_directory}/custom.cfg ]; then
  source ${config_directory}/custom.cfg
elif [ -z "${config_directory}" -a -f  $prefix/custom.cfg ]; then
  source $prefix/custom.cfg;
fi
### END /etc/grub.d/41_custom ###

一般不直接修改grub.cfg配置文件,而是修改特定配置文件后,由grub2-mkconfig命令生成新的grub.cfg文件

配置文件开始的部分,大多是环境设置和默认值设置等,比较重要的当然是默认由哪个选项开机 (set default) 以及默认的秒数 (set timeout),。再来则是每一个菜单的设置,就是在“ menuentry ”这个设置值之后的项目,从上面的配置文档可以看到有两个menuentry,表示当前主机在开启的时候有两个可选择的菜单。

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

其中set root='hd0,msdos1'这里的root指代grub2 配置文件所在的那个设备。安装的时候分区出 / 与 /boot 两个设备,grub2 是在 /boot/grub2 这个位置上, 而这个位置的磁盘文件名为 /dev/sda1,因此完整的 grub2 磁盘名称就是(hd0,1),因为系统采用msdos磁盘分区格式,所以全称为(hd0,msdos1).

# lsblk
NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda               8:0    0  100G  0 disk 
├─sda1            8:1    0    1G  0 part /boot
└─sda2            8:2    0   99G  0 part 
  ├─centos-root 253:0    0   50G  0 lvm  /
  ├─centos-swap 253:1    0    2G  0 lvm  [SWAP]
  └─centos-home 253:2    0   47G  0 lvm  /home
sr0              11:0    1 1024M  0 rom  

其中linux16 ...... root=/dev/mapper/centos-root ......这段代码是 Linux 核心文件以及核心执行时所下达的参数。后面的文件名(/vmlinuz-*)需要跟上面的 set root=xxx 组合才是完整的路径,这里的root 指的是linux 文件系统中,根目录是在哪个设备上。

其中initrd16 /initramfs-*...... 这个是 initramfs 所在的文件名,跟 linux16 那个 vmlinuz-* 相同,这个文件名也是需要搭配set root=xxx 那个项目的设备,才会得到正确的位置。

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

主配置文件

# cat /etc/default/grub
GRUB_TIMEOUT=5   # 指定默认倒数读秒的秒数
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"   #设置发行版的标识名称,一般该名称用来作为菜单的一部分,以便区分不同的操作系统。
GRUB_DEFAULT=saved   # 指定默认由哪一个菜单来开机,默认开机菜单之意
GRUB_DISABLE_SUBMENU=true   # 是否要隐藏次菜单
GRUB_TERMINAL_OUTPUT="console"   # 指定数据输出的终端机格式,默认是通过文字终端机
GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet"   menuentry 括号内的 linux16 项目后续的核心参数
GRUB_DISABLE_RECOVERY="true"
    # 取消救援菜单的制作

假设有以下需求需要配置新的grub:

  1. 开机菜单等待 40 秒钟(GRUB_TIMEOUT参数,后面直接加数字)
  2. 默认用第一个菜单开机(GRUB_DEFAULT参数从0开始依次表示选择的menuentry,saved代表使用 grub2-set-default 来设置哪一个 menuentry 为默认值)
  3. 菜单请显示出来不要隐藏(GRUB_TIMEOUT_STYLE参数可选择值有 menu, countdown, hidden 等等,默认是menu)
  4. 核心外带“elevator=deadline”的参数值
# mv /etc/default/grub /etc/default/grub.bak
# vim /etc/default/grub
GRUB_TIMEOUT=40
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=0
GRUB_TIMEOUT_STYLE=menu
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet elevator=deadline"
GRUB_DISABLE_RECOVERY="true"
# grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.10.0-1160.45.1.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-1160.45.1.el7.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-7736398a16282141bc37306fb9eb32e5
Found initrd image: /boot/initramfs-0-rescue-7736398a16282141bc37306fb9eb32e5.img
done

查看grub.cfg的内容是否发生变化

# grep timeout /boot/grub2/grub.cfg
if [ x$feature_timeout_style = xy ] ; then
  set timeout_style=menu
  set timeout=40
# Fallback normal timeout code in case the timeout_style feature is
  set timeout=40
# grep default /boot/grub2/grub.cfg
# from /etc/grub.d and settings from /etc/default/grub
   set default="${next_entry}"
   set default="0"
function savedefault {
# grep linux16 /boot/grub2/grub.cfg
	linux16 /vmlinuz-3.10.0-1160.45.1.el7.x86_64 root=/dev/mapper/centos-root ro rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet elevator=deadline 
	linux16 /vmlinuz-0-rescue-7736398a16282141bc37306fb9eb32e5 root=/dev/mapper/centos-root ro rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet elevator=deadline 

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:如果还有其他想要手动加上去的菜单项目,或者是其他的需求,那么建议在这里补充

直接指定核心开机

直接用linux的核心开机,通过grub2-mkconfig去抓10_linux这个脚本直接制作即可,当有其他特定参数的时候,可以先到grub.cfg中取得制作的核心菜单项目,将他复制到40_custom,然后再到40_custom当中依旧需求更改。

如下所示,增加一个跳过default.target,强制systemd直接使用graphical.target启动linux的菜单:

# vim /etc/grub.d/40_custom
menuentry 'My graphical CentOS (3.10.0-1160.45.1.el7.x86_64) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted --id 'mygraphical' {
	load_video
	set gfxpayload=keep
	insmod gzio
	insmod part_msdos
	insmod xfs
	set root='hd0,msdos1'
	if [ x$feature_platform_search_hint = xy ]; then
	  search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1'  a2bb0196-8c99-437d-b189-162a79cf17c5
	else
	  search --no-floppy --fs-uuid --set=root a2bb0196-8c99-437d-b189-162a79cf17c5
	fi
	linux16 /vmlinuz-3.10.0-1160.45.1.el7.x86_64 root=/dev/mapper/centos-root ro rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet systemd.unit=graphical.target
	initrd16 /initramfs-3.10.0-1160.45.1.el7.x86_64.img
}

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

重启主机后便可以看到多出了一个可以选择的菜单,此时可以直接进入图形界面(如果有安装相关的 X window 软件)

通过 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 需要这样设置:

menuentry "Windows" {
        insmod chain      # 载入 chainloader 的模块
        insmod ntfs       # 加入 windows 所在的文件系统模块
        set root=(hd0,1)  # 分区位置
        chainloader +1    # 在boot sector 将loader软件读出来
}

假设系统上面使用 MBR 分区,并且出现如下的数据:

# fdisk -l /dev/vda
   Device Boot      Start         End      Blocks   Id  System
/dev/vda1            2048    10487807     5242880   83  Linux
/dev/vda2   *    10487808   178259967    83886080    7  HPFS/NTFS/exFAT
/dev/vda3       178259968   241174527    31457280   83  Linux

其中 /dev/vda2 使用是 windows 7 的操作系统。现在需要增加两个开机选项,一个是取得 windows 7 的开机菜单,一个是回到 MBR 的默认环境。windows 7 在 /dev/vda2 亦即是 hd0,msdos2 这个地方,而 MBR 则是 hd0 ,不需要加上分区,因此整个设置会变这样:

# cat /etc/grub.d/40_custom
menuentry 'Go to Windows 7' --id 'win7' {
        insmod chain
        insmod ntfs
        set root=(hd0,msdos2)
        chainloader +1
}
menuentry 'Go to MBR' --id 'mbr' {
        insmod chain
        set root=(hd0)
        chainloader +1
}

如果要让 windows 变成默认的开机选项,那么在 /etc/default/grub当中根据ID设置“ GRUB_DEFAULT=win7 ” 。

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

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

initramfs 可以将 /lib/modules/.... 内的“开机过程当中一定需要的模块”包成一个文件 (文件名就是 initramfs), 然后在开机时通过主机的 INT 13 硬件功能将该文件读出来解压缩,并且 initramfs 在内存内会仿真成为根目录, 由于此虚拟文件系统 (Initial RAM Disk) 主要包含磁盘与文件系统的模块,因此我们的核心最后就能够认识实际的磁盘, 那就能够进行实际根目录的挂载。

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

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

想重制 initramfs 文件的话, 可以使用 dracut / mkinitrd 来处理

dracut [-fv] [--add-drivers 列表] initramfs文件名 核心版本
选项与参数:
-f:强迫编译出 initramfs ,如果 initramfs 文件已经存在,则覆盖掉旧文件;
-f:显示 dracut 的运行过程;
--add-drivers 列表:在原本的默认核心模块中,增加某些你想要的模块;

核心版本:默认当然是目前运行中的核心版本不过你也可以手动输入其他不同版本;

--modules:将 dracut 所提供的开机所需模块载入,可用模块在下面的目录内
usr/lib/dracut/modules.d/;
--gzip|--bzip2|--xz:尝试使用哪一种压缩方式来进行 initramfs 压缩。默认使用 gzip;
--filesystems :加入某些额外的文件系统支持

以 dracut 的默认功能创建一个 initramfs 虚拟磁盘文件

dracut -v initramfs-test.img $(uname -r)
Executing: /sbin/dracut -v initramfs-test.img 3.10.0-229.el7.x86_64
# 先载入 dracut 本身的模块支持
*** Including module: bash ***                     
*** Including module: nss-softokn ***
*** Including modules done ***
.....
 # 下面两行在处理核心模块
*** Installing kernel module dependencies and firmware ***
*** Installing kernel module dependencies and firmware done ***
.....
# 创建微指令集
*** Generating early-microcode cpio image ***      
*** Constructing GenuineIntel.bin ****
*** Store current command line parameters ***
# 开始创建 initramfs
*** Creating image file ***                        
*** Creating image file done ***
# ll initramfs-test.img 
-rw-------. 1 root root 21235447 Nov 13 21:43 initramfs-test.img

额外加入 e1000e 网卡驱动与 ext4/nfs 文件系统在新的 initramfs 内

# dracut -v --add-drivers "e1000e" --filesystems "ext4 nfs" initramfs-new.img $(uname -r)
 usr/lib/modules/3.10.0-229.el7.x86_64/kernel/drivers/net/ethernet/intel/e1000e
 usr/lib/modules/3.10.0-229.el7.x86_64/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko
 usr/lib/modules/3.10.0-229.el7.x86_64/kernel/fs/ext4
 usr/lib/modules/3.10.0-229.el7.x86_64/kernel/fs/ext4/ext4.ko
 usr/lib/modules/3.10.0-229.el7.x86_64/kernel/fs/nfs
 usr/lib/modules/3.10.0-229.el7.x86_64/kernel/fs/nfs/nfs.ko
可以看得到,新增的模块现在正在新的 initramfs 当中

测试与安装 grub2

# grub2-install [--boot-directory=DIR] INSTALL_DEVICE
选项与参数:
--boot-directory=DIR 那个 DIR 为实际的目录,使用 grub2-install 默认会将
grub2 所有的文件都复制到 /boot/grub2/* ,如果想要复制到其他目录与设备去,
就得要用这个参数。
INSTALL_DEVICE 安装的设备代号

将 grub2 安装在目前系统的 MBR 下面

# grub2-install /dev/sda

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

# df -T | grep xfs
/dev/mapper/centos-root xfs       52403200 2344164  50059036   5% /
/dev/sda1               xfs        1038336  153312    885024  15% /boot
/dev/mapper/centos-home xfs       49250820 1059520  48191300   3% /home
# grub2-install /dev/sda1
Installing for i386-pc platform.
grub2-install: error: hd0 appears to contain a xfs filesystem which isn't known to reserve space for DOS-style boot.  Installing GRUB there could result in FILESYSTEM DESTRUCTION if valuable data is overwritten by grub-setup (--skip-fs-probe disables this check, use at your own risk).

当强制安装的时候,仅会出现warning信息,安装动作会完成

# grub2-install --force --recheck --skip-fs-probe /dev/sda1
Installing for i386-pc platform.
grub2-install: warning: File system `xfs' doesn't support embedding.
grub2-install: warning: Embedding is not possible.  GRUB can only be installed in this setup by using blocklists.  However, blocklists are UNRELIABLE and their use is discouraged..
Installation finished. No error reported.

线上修改功能

将反白标记移动到需要修改的菜单上,按下e键可以进入grub2.cfg的配置文件

方向键移动光标位置,直接删除新增;修改完成之后想直接开机,直接按键[crtl]+cx;想返回菜单选项,直接[crtl]+c 或者是 [esc]。