一、系统引导流程与 GRUB2

引导链路

BIOS → MBR(启动代码)→ GRUB/GRUB2(bootloader)→ 内核 vmlinuz + initramfs → init/systemd

MBR 中的启动程序加载 GRUB,GRUB 负责加载内核(并向内核传递参数),内核挂载临时根文件系统 initramfs,最后交给 systemd 启动各类服务。

MBR 结构

硬盘的第一个逻辑块(扇区)用于存储 MBR 信息,共 512 字节:

MBR(512) = 启动代码(446) + 分区表(64) + 结束标志(2)

各发行版使用的引导程序

发行版 引导程序
CentOS 7 GRUB2
Ubuntu GRUB
Windows GRUB4DOS

GRUB 配置文件位置

  • CentOS 7(BIOS):/boot/grub2/grub.cfg
  • CentOS 7(UEFI):/boot/efi/EFI/centos/grub.cfg
  • Ubuntu:/boot/grub/grub.cfg

GRUB 设备命名

表示法 含义
hd0 第一块硬盘
hd0,1 第一块硬盘的第一个分区(分区号从 1 开始)
hd0,msdos1 第一块硬盘的第一个 MBR 分区
hd1,gpt2 第二块硬盘的第二个 GPT 分区

示例:第一块硬盘第三个分区中 /boot/vmlinuz 的 GRUB 路径为:

(hd0,msdos3)/boot/vmlinuz

常用 GRUB 命令

命令 作用
set 设置 GRUB 环境变量
menuentry 创建菜单项
insmod 加载 GRUB 模块(如 ntfs、ext2、lvm)
linux 指定启动的内核
initrd 指定启动的临时文件系统
chainloader 链式加载其它引导程序
boot 在 GRUB 命令行中启动系统
# 设置菜单显示风格
set timeout_style=menu

# 设置等待时间(秒)
set timeout=30

# 设置 GRUB 根分区
set root='hd0,msdos1'

# 设置默认启动项
set default=2

# 创建菜单项
menuentry 'My Menu Options' {
    ...
}

启动 Linux 的菜单项示例

menuentry 'Ubuntu 16.04.4' {
    set root='hd0,msdos1'
    linux /boot/vmlinuz-4.4.0-116-generic root=/dev/sda1
    initrd /boot/initrd.img-4.4.0-116-generic
}

等价写法(把设备写在路径里):

menuentry 'Ubuntu16.04.4' {
    linux (hd0,msdos1)/boot/vmlinuz-4.4.0-116-generic root=/dev/sda1
    initrd (hd0,msdos1)/boot/initrd.img-4.4.0-116-generic
}

/boot 分区与关键文件

  • /boot 目录建议放在独立分区中;
  • 该分区必须是主分区,并且建议使用 ext2 文件系统。
文件/目录 说明
/boot/grub/grub.cfg GRUB 配置文件,丢失会进入 grub> 命令行
/boot/grub/i386-pc GRUB 模块目录,丢失会进入 grub rescue> 命令行
/boot/vmlinuz-* Linux 内核文件
/boot/initrd.img-*、/boot/initramfs-* 临时文件系统(initramfs)

二、grub.cfg 与 grub2-mkconfig

自动生成配置

# Ubuntu:自动生成 grub.cfg
sudo update-grub

# CentOS 7(BIOS):自动生成 grub.cfg
grub2-mkconfig -o /boot/grub2/grub.cfg

自定义菜单的持久化(关键注意事项)

直接编辑 /boot/grub2/grub.cfg 虽然立即可用,但运行 grub2-mkconfig(或内核升级触发的自动重建)会重新生成该文件,覆盖所有手动添加的 menuentry 块。

自定义菜单项应写入 /etc/grub.d/40_custom:

# 编辑自定义菜单文件
sudo vim /etc/grub.d/40_custom

在该文件中添加自定义 menuentry 块,每行格式与 grub.cfg 完全一致,例如:

menuentry "Windows 7" {
    insmod ntfs
    set root=(hd0,1)
    chainloader +1
}
  • 文件必须保持可执行权限(-rwxr-xr-x),否则 grub2-mkconfig 会忽略它;
  • 修改后执行 grub2-mkconfig -o /boot/grub2/grub.cfg 重新生成即可保留自定义菜单。

默认启动项

# 将默认启动项设为菜单中的某个条目(按名称匹配)
grub2-set-default "Windows 7"

# 查看当前保存的默认项
grub2-editenv list

# 查看 GRUB 环境变量文件
cat /boot/grub2/grubenv

需要在 /etc/default/grub 中设置 GRUB_DEFAULT=saved,使系统记住并使用 grub2-set-default 设定的值:

# 编辑 /etc/default/grub,确保包含以下行
GRUB_DEFAULT=saved

/boot/grub2/grubenv 中记录了 saved_entry 等下次启动相关的变量,一般通过 grub2-set-default、grub2-reboot 等命令维护,不建议直接手工编辑:

vim /boot/grub2/grubenv

BIOS 与 UEFI 的路径差异

启动模式 GRUB 配置文件路径 对应命令
BIOS /boot/grub2/grub.cfg grub2-mkconfig -o /boot/grub2/grub.cfg
UEFI /boot/efi/EFI/centos/grub.cfg grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg

执行 grub2-mkconfig 时务必指定正确的输出路径,UEFI 系统下若误写入 /boot/grub2/grub.cfg,配置不会生效。


三、CentOS 7 下添加 Windows 7 双系统引导

CentOS 7 使用 GRUB2 作为引导程序。当先安装 Windows 7、再安装 CentOS 7 时,GRUB2 通常会自动识别 Windows;若未识别,可手工添加引导菜单。适用于 CentOS 7 + GRUB2 + Windows 7 双系统环境。

1. 编辑 GRUB2 配置文件

vim /boot/grub2/grub.cfg

在合适位置添加如下菜单项:

menuentry "Windows 7" {
    insmod ntfs
    set root=(hd0,1)
    chainloader +1
}

参数说明:

  • insmod ntfs:加载 NTFS 模块,使 GRUB 能识别 Windows 分区;
  • hd0 代表第一块硬盘;
  • 1 代表 Windows 7 所在的分区号,根据实际情况修改,例如 Windows 装在第二分区则为 (hd0,2);
  • chainloader +1 表示将引导权链式转交给该分区的引导扇区(第一个扇区)。

保存退出。

注意:在较新的 GRUB2 实践中,更推荐将自定义菜单写到 /etc/grub.d/40_custom 后执行 grub2-mkconfig -o /boot/grub2/grub.cfg,避免内核升级或重新生成配置时 grub.cfg 被覆盖。原教程是直接修改 grub.cfg,此处保留作记录。

2. 将 Windows 7 设为默认启动项

grub2-set-default "Windows 7"

3. 检验默认项是否设置成功

grub2-editenv list

输出中 saved_entry 应显示为 Windows 7。

4. 查看/编辑 GRUB2 环境文件

vim /boot/grub2/grubenv

5. 在 GRUB 命令行临时引导 Windows

在 GRUB 菜单界面按 c 进入命令行,手工链式引导 Windows(假设 Windows 在 /dev/sda2):

set root=(hd0,2)
chainloader +1
boot

6. 多系统菜单完整示例

将 Ubuntu/Mint/CentOS 的启动文件统一放在 boot 分区(如 /dev/sda3),通过 GRUB 配置多系统菜单:

  • Ubuntu/Mint 使用 GRUB,配置在 (hd0,3)/grub/grub.cfg;
  • CentOS 7 使用 GRUB2,配置在 (hd0,3)/grub2/grub.cfg。
系统 配置文件 内核文件
Ubuntu/Mint (hd0,3)/grub/grub.cfg vmlinuz-4.4.0-116-generic
CentOS 7 (hd0,3)/grub2/grub.cfg vmlinuz-3.10.0-862.el7.x86_64

在 GRUB 命令行分别启动各系统:

# Ubuntu
linux (hd0,3)/vmlinuz-4.4.0-116-generic root=/dev/sda1 quiet splash
initrd (hd0,3)/initrd.img-4.4.0-116-generic
boot

# Mint
linux (hd0,3)/vmlinuz-4.15.0-20-generic root=/dev/mapper/up-mint quiet splash
initrd (hd0,3)/initrd.img-4.15.0-20-generic
boot

# CentOS 7
linux (hd0,3)/vmlinuz-3.10.0-862.el7.x86_64 root=/dev/mapper/up-centos quiet splash
initrd (hd0,3)/initramfs-3.10.0-862.el7.x86_64.img
boot

完整的多系统 grub.cfg 示例:

insmod all_video
insmod gfxterm
insmod gettext
insmod lvm
insmod part_msdos
insmod ext2
insmod exfat
insmod iso9660
insmod loopback
insmod jpeg
insmod png
insmod cryptodisk

set gfxmode=auto
set locale_dir=$prefix/locale
set lang=zh_CN
set timeout_style=menu
set timeout=5
set default=0

background_image /boot/grub/bg.jpg

menuentry 'Ubuntu 16.04' {
    linux (hd0,3)/vmlinuz-4.4.0-116-generic root=/dev/sda1 quiet splash
    initrd (hd0,3)/initrd.img-4.4.0-116-generic
}

menuentry 'Mint 19' {
    linux (hd0,3)/vmlinuz-4.15.0-20-generic root=/dev/mapper/up-mint quiet splash
    initrd (hd0,3)/initrd.img-4.15.0-20-generic
}

menuentry 'CentOS 7' {
    linux (hd0,3)/vmlinuz-3.10.0-862.el7.x86_64 root=/dev/mapper/up-centos quiet splash
    initrd (hd0,3)/initramfs-3.10.0-862.el7.x86_64.img
}

menuentry 'Windows 7' {
    set root=(hd0,2)
    chainloader +1
}

menuentry 'CentOS 7 Install' {
    set root=(hd0,6)
    linux /vmlinuz linux repo=hd:/dev/sda6:/
    initrd /initrd.img
}

menuentry 'Mint 19 Install' {
    set root=(hd0,6)
    loopback loop /mint19.iso
    set root=(loop)
    linux /casper/vmlinuz boot=casper iso-scan/filename=/mint19.iso quiet splash --
    initrd /initrd.img
}

menuentry 'Ghost' {
    set root=(hd0,6)
    linux16 /memdisk c=2000 h=4 s=36 floppy
    initrd /ghost.img
}

menuentry '重启' {
    reboot
}

menuentry '关机' {
    halt --no-apm
}

四、单用户模式、救援模式与 root 密码重置

运行级别与目标

运行级别 名称 说明
1 Single user mode 单用户模式,用于系统维护,只启动最少服务,不启动网络
3 Multi-user 多用户命令行模式
5 Graphical 图形界面模式

CentOS 7 已用 systemd target 取代运行级别,与单用户/救援相关的目标是:

target 对应说明
rescue.target 救援模式,等价于传统单用户模式,挂载本地文件系统、启动极少服务
emergency.target 紧急模式,只以只读方式挂载根文件系统,不启动任何服务,用于 fstab 写错等严重故障

在 GRUB 菜单中按 e 编辑目标菜单项,在 linux16/linux 内核行末尾追加参数即可临时进入:

systemd.unit=rescue.target
# 或
systemd.unit=emergency.target

编辑完成后按 Ctrl + x 启动。

忘记 root 密码的处理思路

思路一(推荐,CentOS 7 通用):在 GRUB 菜单按 e 编辑启动项,在内核行末尾追加 rd.break,按 Ctrl + x 启动,进入 initramfs 的紧急 shell 后:

# 此时真实根文件系统以只读方式挂载在 /sysroot
mount -o remount,rw /sysroot
chroot /sysroot

# 修改 root 密码
passwd root

# 若启用了 SELinux,必须创建自动重新打标记的标志文件
touch /.autorelabel

exit
exit        # 系统继续启动并自动重新打标记(耗时较长),完成后自动重启

思路二:在内核行末尾追加 init=/bin/bash(或 CentOS 6 及更早的 single)进入 shell,再 mount -o remount,rw / 后执行 passwd root。

思路三:使用光盘/U 盘启动进入救援模式(安装介质菜单中的 Rescue installed system),挂载并 chroot 到原系统后改密码(步骤见下一节的 chroot 修复流程)。

安全提示:可以给 GRUB 加密码,防止他人在启动时修改 GRUB 参数进入单用户模式修改 root 密码。但 GRUB 密码并不绝对安全,攻击者仍可通过外部介质的 rescue 模式进入系统,物理访问控制才是根本。


五、MBR 与引导故障修复

1. MBR 与分区表的备份与恢复

以下两种备份方式任选其一:

# 1. 连同启动加载程序(MBR 全部 512 字节)一起备份
head -c 512 /dev/sda > /some/where/boot_sector.bin

# 2. 仅备份分区表(MBR 中偏移 446 开始的 64 字节)
head -c 510 /dev/sda | tail -c 64 > /some/where/partition_table.bin

恢复(慎用,会覆盖目标盘的 MBR):

dd if=./mbr.txt of=/dev/sda bs=1 count=512

只恢复分区表时应写回 64 字节到偏移 446 处(dd ... bs=1 seek=446 count=64),不要整体覆盖 512 字节,避免破坏正常的启动代码。

2. 情况一:进入 grub> 命令行

当 grub.cfg 配置文件错误或丢失,开机会进入 grub> 命令行,此时可手工引导系统:

set root=(hd0,1)
linux /boot/vmlinuz-4.4.0-130-generic root=/dev/sda1
    # 输入 linux /boot/vmlinuz- 后可按 Tab 补全内核文件名
initrd /boot/initrd.img-4.4.0-130-generic
boot

进入系统后重新生成配置文件(update-grub 或 grub2-mkconfig -o /boot/grub2/grub.cfg)即可恢复菜单。

3. 情况二:进入 grub-rescue> 命令行

当 GRUB 模块目录(i386-pc)丢失时,会进入 grub-rescue> 命令行。前提是已知 GRUB 目录所在分区(例如第一块硬盘的第一个分区):

set prefix=(hd0,1)/grub       # 设置 grub 程序(模块)根目录
set root=(hd0,1)              # 设置默认根分区
insmod normal                 # 导入 normal 核心模块
normal                        # 运行 normal 模块,进入 grub 菜单

4. 直接重装 GRUB 引导程序(BIOS + MBR)

# 将 GRUB 引导程序写入 MBR,并生成 /boot 下相关文件
sudo grub-install /dev/sda

# Ubuntu 自动生成 grub.cfg
sudo update-grub

grub-install /dev/sda 会自动将 GRUB 引导程序写入 MBR,并在 /boot 下生成 GRUB 相关文件。CentOS 7 下对应的配置生成命令是 grub2-mkconfig -o /boot/grub2/grub.cfg(注意该命令会重新生成并覆盖 grub.cfg,手工添加的 menuentry 会丢失,自定义菜单请写入 /etc/grub.d/40_custom)。

5. 借助第三方 Linux 系统修复(chroot 流程)

适用于根分区完整、只是引导程序或相关文件丢失导致无法启动的情况。可借助 U 盘、光盘或网络启动的 Linux 系统修复:

# 1. 挂载待修复系统的根分区
sudo mount /dev/sda1 /mnt

# 2. 挂载 boot 分区到 /mnt/boot
sudo mount /dev/sda3 /mnt/boot/

# 3. 绑定挂载内核相关目录(proc、sys、dev、tmp)
sudo mount -o bind /proc /mnt/proc/
sudo mount -o bind /sys  /mnt/sys/
sudo mount -o bind /dev  /mnt/dev/
sudo mount -o bind /tmp  /mnt/tmp/

# 4. 切换到待修复系统
sudo chroot /mnt

# 5. 重装 GRUB
sudo grub-install /dev/sda

在 chroot 环境中同样可以执行 passwd root 重置密码、修正 /etc/fstab 等操作,完成后 exit 退出并重启。


练习

练习 1:分区方案(含 Swap)

按照以下方案使用 fdisk 完成分区,并通过 t 修改分区类型:

分区 大小 用途 分区类型 ID
第一个分区 50G CentOS 根分区 20(不要动)
第二个分区 4G swap 19(不要动)
第三个分区 4G boot 分区 4
第四个分区 扩展分区 — —
└ 第二个逻辑分区 50G /home 20
└ 第三个逻辑分区 30G ubuntu 20
└ 第四个逻辑分区 20G mint 20
└ 最后一个逻辑分区 剩余空间 Windows D 盘 7

注意:第一个/第二个分区已存在时不要动;分区结束后用 partprobe 刷新设备文件,再按需格式化、挂载。

练习 4:添加 Windows 引导项

  1. 在 /etc/grub.d/40_custom 中添加 Windows 7 的 menuentry,确认文件具有可执行权限;
  2. 执行 grub2-mkconfig -o /boot/grub2/grub.cfg 重新生成配置;
  3. 用 grub2-set-default "Windows 7" 设为默认项,grub2-editenv list 验证 saved_entry;
  4. 确认 /etc/default/grub 中 GRUB_DEFAULT=saved。

练习 5:引导故障修复演练

  1. 备份 MBR(512 字节)和分区表(64 字节)到安全位置;
  2. 重命名 /boot/grub2/grub.cfg,重启观察进入 grub> 命令行;
  3. 在 grub> 下用 set root、linux、initrd、boot 手工引导进入系统;
  4. 用 grub2-mkconfig 恢复配置文件;
  5. 演练在 GRUB 菜单追加 rd.break,通过 chroot /sysroot 重置 root 密码(记得 touch /.autorelabel)。
最后修改:2026 年 09 月 20 日
如果觉得我的文章对你有用,请随意赞赏