# grub2 配置centos7，ubuntu
Date: 2019-05-16


##  一 虚拟机安装centos7，ubuntu配置grub2启动

## 1\. 环境准备及安装

1.  VMWARE 安装centos7 ， 参考[鸟哥私房菜第三章](http://linux.vbird.org/linux_basic/0157installcentos7.php)

2\. 下载了[Ubuntu](https://www.ubuntu.com/download)最新的server版本。

3\. 虚拟机增加硬盘（选用默认SCSI类型）,安装 Ubuntu19， Ubuntu镜像文件挂载到VMWARE的CDROM。

4.  VMWARE重启后按F12，修改BIOS中的Boot菜单项的启动顺序， 将CDROM上移到Hard disk上。

5\. 重启虚拟机安装提示安装， 将Ubuntu安装到新增加的硬盘上。我安装 Ubuntu 按照LVM方式进行分区。

## 2\. 配置 boot loader 软件grub2：

下面使用两种方式配置下grub2：

### 1）. 通过grub2-mkconfig 自动扫描：

-     **先看下本地磁盘的信息使用 lsblk命令**

\[root@centosgpt grub.d\]# **lsblk**

NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT

sda 8:0 0 100G 0 disk

├─sda1 8:1 0 2M 0 part

├─sda2 8:2 0 1G 0 part /boot

├─sda3 8:3 0 59G 0 part

│ ├─centos-root 253:0 0 50G 0 lvm /

│ ├─centos-swap 253:1 0 4G 0 lvm \[SWAP\]

│ └─centos-home 253:3 0 5G 0 lvm /home

├─sda5 8:5 0 1G 0 part

│ └─md0 9:0 0 2G 0 raid5

│ └─raidvg-raidlv 253:2 0 1.5G 0 lvm /srv/raidlvm

├─sda6 8:6 0 1G 0 part

│ └─md0 9:0 0 2G 0 raid5

│ └─raidvg-raidlv 253:2 0 1.5G 0 lvm /srv/raidlvm

└─sda7 8:7 0 1G 0 part

└─md0 9:0 0 2G 0 raid5

└─raidvg-raidlv 253:2 0 1.5G 0 lvm /srv/raidlvm

sdb 8:16 0 20G 0 disk             #安装Ubuntu的硬盘

├─sdb1 8:17 0 1M 0 part

├─sdb2 8:18 0 1G 0 part

└─sdb3 8:19 0 19G 0 part

└─ubuntu--vg-ubuntu--lv 253:4 0 4G 0 lvm

sr0 11:0 1 1024M 0 rom

-        **使用grub2-mkconfig 重建 grub.cfg**

\[root@centosgpt ~\]# **grub2-mkconfig -o /boot/grub2/grub.cfg**  
Generating grub configuration file ...  
Found linux image: /boot/vmlinuz-3.10.0-862.el7.x86\_64  
Found initrd image: /boot/initramfs-3.10.0-862.el7.x86\_64.img  
Found linux image: /boot/vmlinuz-0-rescue-8c13e5705e2d4850ae230d7d1d1b5ab1  
Found initrd image: /boot/initramfs-0-rescue-8c13e5705e2d4850ae230d7d1d1b5ab1.img  
Found Ubuntu 19.04 (19.04) on /dev/mapper/ubuntu--vg-ubuntu--lv  
done

-       **提前看下启动页面的效果**

\[root@centosgpt ~\]# **awk -F\\' '$1=="menuentry " {print i++ " : " $2}' /etc/grub2.cfg**

0 : CentOS Linux (3.10.0-862.el7.x86\_64) 7 (Core)  
1 : CentOS Linux (0-rescue-8c13e5705e2d4850ae230d7d1d1b5ab1) 7 (Core)  
2 : Ubuntu 19.04 (19.04) (on /dev/mapper/ubuntu--vg-ubuntu--lv)

### 2）. 通过chainloader配置

- **修改 /etc/grub.d/40\_custom 配置文件：**
    
    \[root@centosgpt ~\]# **cat /etc/grub.d/40\_custom**  
    #!/bin/sh  
    exec tail -n +3 $0
    
    submenu mainmenu {  
    menuentry 'Go to Centos7' --id 'centos' {  
    insmod chain  
    insmod xfs  
    insmod part\_gpt  
    set root=(hd0)  
    chainloader +1  
    }  
    menuentry 'Go to Ubuntu' --id 'ubuntu' {  
    insmod chain  
    insmod ext2  
    insmod part\_gpt  
    set root=(hd1)  
    chainloader +1  
    }  
    menuentry 'Go to CentOs' --id 'Centos' {  
    set root=(hd0)  
    chainloader +1  
    }  
    }
    
- **使用grub2-mkconfig 重建 grub.cfg**

\[root@centosgpt ~\]# **grub2-mkconfig -o /boot/grub2/grub.cfg**

Generating grub configuration file ...  
Found linux image: /boot/vmlinuz-3.10.0-862.el7.x86\_64  
Found initrd image: /boot/initramfs-3.10.0-862.el7.x86\_64.img  
Found linux image: /boot/vmlinuz-0-rescue-8c13e5705e2d4850ae230d7d1d1b5ab1  
Found initrd image: /boot/initramfs-0-rescue-8c13e5705e2d4850ae230d7d1d1b5ab1.img  
Found Ubuntu 19.04 (19.04) on /dev/mapper/ubuntu--vg-ubuntu--lv  
done

-       **提前看下启动页面的效果**

\[root@centosgpt ~\]# **awk -F\\' '$1=="menuentry " {print i++ " : " $2}' /etc/grub2.cfg**  
0 : CentOS Linux (3.10.0-862.el7.x86\_64) 7 (Core)  
1 : CentOS Linux (0-rescue-8c13e5705e2d4850ae230d7d1d1b5ab1) 7 (Core)  
2 : Ubuntu 19.04 (19.04) (on /dev/mapper/ubuntu--vg-ubuntu--lv)  
3 : Go to Centos7  
4 : Go to Ubuntu  
5 : Go to CentOs

-       **配置过程中出现的问题**

1\. /etc/grub.d/40\_custom 是脚本，修改时删除了1 #!/bin/sh 红色部分，grub2-mkconfig生成报错

        2. 由于安装时使用的是两块硬盘安装，比较[鸟哥第十九章](http://linux.vbird.org/linux_basic/0510osloader.php#grub)， 中的在一个磁盘 的分区上安装操作系统简单些， 不用配置相关分区信息。

## 二 预备知识

       整理这篇文档是 [极客时间](https://time.geekbang.org/) 刘超《趣谈Linux操作系统》的一篇课堂作业，因为仅是简单配置Linux 不同两个发行版本（Linux distribution）， 本例子使用的grub2相关配置还是比较简单的。

      这里把涉及相关知识整理了一下。

###    1 硬盘分区

    **分区：**是磁盘一个固定大小的子集，在操作系统内将其视为一个单元。

-     有助于数据的隔离，保证数据安全；
-    数据集中在固定分区后，有助于磁盘读取性能。

   **分区表：**是操作系统在磁盘上维护的表， 用于描述磁盘分区。

-    MBR：Master Boot Record 应用与IBM PC 兼容机；
-    GPT：  GUID Partition Table UEFI 标准中的分区格式；
-    APM： Apple partion map ，早期使用Power PC芯片的 Apple PC
-    BSD disklabel：Sun OS

    **MBR：**

-    位置：在磁盘的一个扇区存放了开机的管理程序及分割表。
-    构成：开机管理程序446字节+分割表64字节+结束标识2字节
-    分区：
    - 类型：主（Primary），扩展（Extended）
    - 数量：主分区与扩展分区最多4个， 通过扩展分区再划分逻辑分区SATA硬盘可以支持到63+。
    - 大小：64个字节进行设置， 4个字节标识扇区起始位置
-    限制：
    - 分区个数少：最多四个分区，扩展分区只能有一个
    - 容量受限：单个分区信息使用16个字节，4个字节能标识的扇区的数， 2的8bit\*4次方 \* 512byte（扇区大小）= 2的41次方 =2T

- - 引导扩展问题：管理程序仅446bytes无法支持更多功能
    - 备份问题：MBR存放到再第一个512区块中，破坏后无法使用。

    **GPT：**

     GPT是UEFI标准的一部分目标是取代MBR ，他解决MBR存在的大多数问题，而且得到了大多数操作系统的支持。实验安装Centos7 和Ubuntu 都使用gpt。

-     位置： 兼容性考虑， 硬盘的第一个扇区仍然是MBR，LBA0
-     构成：
    -  LBA0  ：MBR
    -  LBA1 ：GPT表头
    -  LBA2-33 ：数据区
    -  LBA34：备份区
-     分区：
    - 类型： GPT不再区分主，扩展，逻辑分区，每个分区独立。
    - 个数： 在LBA2-33，每个LBA支持4个分区， 4\*32=128个分区
    - 大小： 每笔记录128字节，其中8个字节存放，扇区起始位置， 2的8bit\*8次方 \* 512byte（扇区大小）= 2的73次方 = 8ZB

### 2\. 系统开机流程

####     1）**BIOS/UEFI:**

   BIOS基本输入输出系统是系统打开执行的第一个程序（fireware），大多数情况下，他存储在主板本身闪存（CMOS）内与系统存储无关。

   UEFI固件支持读取分区表和文件系统，UEFI不会在MBR启动任何代码， 无论是否存在， 他启动依赖NVRAM中配置的启动条目。

####    2） **使用BIOS**

1. 系统开机，加电自检（POST:  power-on self-test ）；
2. 自检完成后， BIOS初始化一些启动必要的硬件如硬盘，键盘等；
3. BIOS载入运行第一块硬盘上的前面440字节中的MBR启动代码（the Master Boot Record Bootstrap code area）；
4. Boot loader 在MBR boot code第一个阶段完成后， 通过一下任一个启动第二阶段：
    1.  在MBR后的后面的硬盘扇区 ， post-MBR gap
    2.  可分区硬盘或无法分区的软盘关盘的  volume boot record VBR
    3.  BIOS boot 分区（仅限BIOS/GPT）
5. 启动实际的bootloader
6. bootloader载入操作系统通过直接载入（ directly loading）或者链式加载（ chain-loading）的方式

##### **grub的stages**

- - stage 1位于MBR中主要工作是跳转到第二部分， 由于MBR能够保存的数据有限
    - stage 2分指向/boot/grub grub的配置文件， 他包含了所有复杂的用户接口及选项，第二部分可以位于磁盘的任何地方。如果第二部分不存在，GRUB会停止引导。
    - stage1.5 如果引导信息足够小并且可以存放MBR后面的区域，存在 也就是上面说得 post-MBR gap

<figure>

![](/wp-content/uploads/2019/05/GNU_GRUB_components.svg_.png)

<figcaption>

图片来自

</figcaption>

</figure>

**MBR-分区结构**

- - core.img存放在MBR后的 MBR-gap
    - core.img 抓取 /boot/grub  （可以是/boot或/下）

**GPT分区结构**core.img可以存放 BIOS boot分区中。 

- - core.img存放在BIOS boot中
    - core.img 抓取 /boot/grub  （可以是/boot或/下）

**VBR** ：与chaining-loading 一起出现， 可以将OS安装到磁盘的某一个分区，bootloader存放到分区的boot record。鸟哥私房菜19章节中， 操作系统装在统一磁盘上的话用到这个概念。

####    **2）使用 UEFI**   

1. 系统开机，加电自检（POST:  power-on self-test ）；
2. 自检完成后， UEFI初始化一些启动必要的硬件；
3. 固件（Firmware） 读取NVRAM中的引导条目， 确定要启动哪个EFI应用以及要从哪里启动（哪个硬盘和分区）
    1. 引导条目可能是一磁盘， 这种情况下， 固件（firmware）查找 EFI 系统分区 并且尝试在回退引导路径\\EFI\\BOOT\\BOOTX64.EFI(IA32位UEFI使用BOOTX32.EFI)中查找EFI应用程序， 这是UEFI可以移动介质启动的工作原理。
4. 固件（Firmware）启动EFI 应用程序
    1. 可以使用EFISTUB的booter loader 或者 操作系统内核
    2. 可以是一些其他EFI应用， 比如UEFI shell或者bootmanager如systemd-boot或者eEFInd。

### 3\. grub2介绍

#### 1）grub2 配置文件：

- **/etc/default/grub**：包含grub菜单的设置
- **/etc/default/grub.d(ubuntu)**:  包含grub菜单的设置

**GRUB\_TIMEOUT**     **#**倒计时设置  
**GRUB\_DEFAULT**    #设定那个一个菜单进行开机  
**GRUB\_DISABLE\_OS\_PROBER #** 使用os-prober 检查其他操作系统

- **/etc/grub.d/**： 这个目录下包含GRUB脚本， 执行grub(2)-mkconfig按照特定顺序生成grub.cfg

**00\_header**: 载入默认grub.cfg配置

**10\_\***: 本地已经安装的发行版本菜单选项， **10\_linux**

**20\_\***: 第三方应用。

**30\_os-prober**: 自动发现系统系统上安装其他系统

**40\_custom:** 用户自定义的一些启动菜单

- **/boot/grub/grub.cfg**： 这个文件是主配置文件， 不可以手工修改通过grub2-mkconfig（centos7 ）/ grub-mkconfig （ubuntu）生成

####  2）  grub2 配置命令：

**菜单显示：** menuentry， submenu

**通用命令**： serial， terminal\_input, terminal\_output, terminfo

**菜单配置**：chainloader，  linux ，date， initr16， insmod，

**网络配置**： net\_add\_addr， net\_add\_dns

[GRUB2 Command](https://www.gnu.org/software/grub/manual/grub/grub.html#Commands) 有详细描述

#### 3）menuentry配置：

##### 1\. 直接指定核心开机：

通过grub2-mkconfig 通过10\_linux生成 如下：

```
menuentry 'CentOS Linux (3.10.0-862.el7.x86_64) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-862.el7.x86_64-advanced-c8e31f5f-1e08-47ed-89c3-c90ce868ac18' {
        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-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 --hint='hd0,gpt2'  0610d7ed-4486-465d-87e5-ac74cdf92150
        else
          search --no-floppy --fs-uuid --set=root 0610d7ed-4486-465d-87e5-ac74cdf92150
        fi
        linux16 /vmlinuz-3.10.0-862.el7.x86_64 root=/dev/mapper/centos-root ro crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet
        initrd16 /initramfs-3.10.0-862.el7.x86_64.img
}
```

**menuentry** 'CentOS Linux (3.10.0-862.el7.x86\_64) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry\_id\_option 'gnulinux-3.10.0-862.el7.x86\_64-advanced-c8e31f5f-1e08-47ed-89c3-c90ce868ac18'

**配置菜单名称与风格**， $menuentry\_id\_option 根据条件设置是否为id

**load\_video**  
**set** **gfxpayload=keep**  
**insmod** gzio  
**insmod** part\_gpt  
**insmod** xfs

设置图形界面载入相关磁盘，分区，压缩相关驱动

**set root**\='hd0,gpt2'

**设置配置文档的位置** ，硬盘从0开始编号， 分区从1开始编号， 我们centos7安装再/dev/sda2 

NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT  
sda 8:0 0 100G 0 disk  
├─sda1 8:1 0 2M 0 part  
├─sda2 8:2 0 1G 0 part /boot

**search** --no-floppy --fs-uuid --set=root --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2 --hint='hd0,gpt2' 0610d7ed-4486-465d-87e5-ac74cdf92150

按照文件 ，label，UUID查找设备

\[root@centosgpt ~\]# cat /etc/fstab

...  
/dev/mapper/centos-root / xfs defaults 0 0  
UUID=0610d7ed-4486-465d-87e5-ac74cdf92150 /boot xfs defaults 0 0  
...

**linux16** /vmlinuz-3.10.0-862.el7.x86\_64 root=/dev/mapper/centos-root ro crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet

**载入Linux kernel image**， 在16bit模式下   这个指令只用于X86系统

**nitrd16** /initramfs-3.10.0-862.el7.x86\_64.img

**载入inital ramdisk** ， 为启动Kernal image，  这个指令只用于X86系统

##### 2\. 通过chainloader转交控制权：

```
### BEGIN /etc/grub.d/40_custom ###

submenu mainmenu {
menuentry 'Go to Centos7' --id 'centos' {
        insmod chain
        insmod xfs
        insmod part_gpt
        set root=(hd0)
        chainloader +1
}
menuentry 'Go to Ubuntu' --id 'ubuntu' {
        insmod chain
        insmod ext2
        insmod part_gpt
        set root=(hd1)
        chainloader +1
}
menuentry 'Go to CentOs' --id 'Centos' {
       set root=(hd0)
       chainloader +1
}
}
```

**chainloader** +1

boot的控制权交给下一个boot sector或MBR/GPT内的boot loader。+1表示获取当前分区的第一个扇区。

#### 4）grub2相关命令：

grub2-install : 安装grub到指定设备

grub2-mkconfig（ubuntu：grub-mkconfig/update-grub）：生成grub.cfg

grub2-set-default: 后面参数为数字， 代表启动列表中内核索引， grub2-set-default　2 ， 选择第三项

> saved\_entry 值设置为最新安装的内核包类型内核的名称），grub2-set-default最终通过修改该值来设置要选择的内核版本。

## 参考：

[centos wiki Grub2](https://wiki.centos.org/zh/HowTos/Grub2)

[鸟哥私房菜第19章](http://linux.vbird.org/linux_basic/0510osloader.php#grub)

[鸟哥私房菜第2章](http://linux.vbird.org/linux_basic/0130designlinux.php#partition_table)

[Disk Partitioning wiki](https://en.wikipedia.org/wiki/Disk_partitioning#Primary_partition)

[GNU doc BIOS installation](https://www.gnu.org/software/grub/manual/grub/grub.html#BIOS-installation)

[Arch boot process](https://wiki.archlinux.org/index.php/Arch_boot_process#Boot_loader)

[BIOS boot partition](https://en.wikipedia.org/wiki/BIOS_boot_partition)

[Volume boot record](https://en.wikipedia.org/wiki/Volume_boot_record)

[GRUB bootloader - Full tutorial](https://www.dedoimedo.com/computers/grub.html)

[GRUB2 boot loader-Full tutorial](https://www.dedoimedo.com/computers/grub-2.html)

https://docs.fedoraproject.org/en-US/fedora/latest/system-administrators-guide/kernel-module-driver-configuration/Working\_with\_the\_GRUB\_2\_Boot\_Loader/

