暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

深入解析GRUB

老柴杂货铺 2025-04-04
6

GRUB英文全称 GRand Unified Bootloader 俗称引导程序是硬盘中的软件,它可以启动用户在计算机中的多个操作系统所以也叫多重启动管理器。

目前主流版本是 GRUB2,在windows中也有类似的引导程序 ntloader 虽然它也可以引导Linux操作系统但是比较麻烦;

一、GRUB的技术演进之路

1.1 启动管理器的革命

在传统BIOS时代,LILO(Linux Loader)曾是Linux系统的默认启动加载程序。其简单的配置文件结构和直接写入MBR的运作方式,在早期满足了基本需求。但随着多系统启动需求的激增,LILO的局限性逐渐显现:配置文件修改后必须重新安装、不支持动态内核检测等问题日益突出。

1.2 GRUB的诞生与进化

1995年,Erich Boleyn主导开发的GRUB(GRand Unified Bootloader)首次亮相。其革命性的预启动环境设计支持交互式命令操作,配合模块化架构实现动态配置。2002年推出的GRUB 2(原称GRUB Legacy)更是实现了对UEFI的完整支持,新增的脚本支持、主题定制等功能使其成为现代Linux发行版的标配。

对比分析(GRUB Legacy vs GRUB2):

配置文件:menu.lst → grub.cfg

架构设计:单层结构 → 模块化加载

扩展能力:有限命令 → 完整脚本支持

硬件支持:传统BIOS → UEFI+Secure Boot**

二、GRUB2的核心架构解析

2.1基础介绍

2.1.1 设备名称:

GRUB识别的设备名称不区分IDE硬盘和SCSI硬盘,统一使用hd*来表示既(hdx,y))标识某个硬盘中的某个分区x表示硬盘号,y表示分区号(他们都是从0开始计数),同时软盘使用fdx来标识即(fdx) x为硬盘号,x从0开始计数

(1) 在windows中系统的第一个硬盘驱动器表示为(hd0),此时该磁盘的第一个分区表示为(hd0,0)它就是我们所说的C盘;

(2) 由于主分区受限于磁盘格式常常为四个,所以第一个磁盘的主分区分别用(hd0,0)~(hd0,3)来表示,而逻辑分区则是从(hd0,4)开始计算, 在Windows中分区都是一个主分区其余是逻辑分区,因此C盘用(hd0,0),D盘用(hd0,4)来表示

2.1.2 GRUB 位置

GRUB启动代码(boot.img)直接安装在 MBR 中,然后执行 GRUB 内核镜像(core.img),最后从/boot/grub中读取配置和其他功能代码。

如下图所示,GRUB 的执行顺序为 boot.img --> core.img --> /boot/grub/。

BIOS 引导方式中,MBR 分区表和 GPT 分区表的 GRUB 引导文件所放分区不同:

(1) 在 MBR 分区表中,boot.img 和 core.img 都在 MBR 中。MBR 虽然只占用一个扇区(512Byte),但是其所在的磁道是空闲的,不会用于分区,可以放下 core.img。

(2) 在 GPT 分区表中,MBR 为 protected MBR(为兼容 MBR,在硬盘起始位置保留的空间),后面并没有空间放core.img,需要建一个专门的分区来放,称为BIOS boot partition,该分区的文件类型为unformatted,flag 为BOIS_grub,该 flag 用于标识core.img所要安装到的分区。

如果使用 UEFI 引导,GRUB 读取的是 ESP 分区中的数据,不需要 flag 为 BIOS_grub的分区。 

2.1.3 GRUB 文件介绍

以Linux中GRUB引导程序为例,其重要的部分是一堆文本文件和两个脚本文件,即下面列出的文件目录;

/etc/default/grub : 文本文件,设置通用配置变量和 Grub 2 菜单(见下方 常见用户设置 )的其它特性。

/etc/grub2.cfg :

/etc/grub2-efi.cfg : 

/etc/grub.d: 文件夹,定义每个菜单项的所有脚本都放置在这里,里面以两位数字+脚本名称的格式存放,为的是在构建 Grub 2 菜单时定义脚本的执行顺序以及相应菜单项的顺序;

/boot/grub/grub.cfg : 

Grub设置通用配置变量

    # 配置文件信息
    [root@localhost ~]# ls -alhs /etc/default/grub
    4.0K -rw-r--r--. 1 root root 279 7月  17 2020 /etc/default/grub
    # 打开GRUB配置文件可以看见一些常见的变量
    [root@localhost ~]$ cat /etc/default/grub
    # - 指定启动默认菜单项之前的停留时间
    GRUB_TIMEOUT=5
    # - 获取系统的发行版信息
    GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
    # - 指定默认的启动项,可以设置为数字值或者saved,比如 0 表示第一个菜单项,或者设置为 “saved” 将指向上一次启动时选中的菜单项
    GRUB_DEFAULT=saved
    GRUB_DISABLE_SUBMENU=true
    GRUB_TERMINAL_OUTPUT="console"
    # - 传递给所有 Linux 菜单项的内核命令行参数。
    GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet"
    # - 是否禁用恢复模式不生成恢复模式菜单项。
    # 恢复模式菜单项会以单用户模式启动发行版,这种模式下允许你利用命令行工具修复系统。
    GRUB_DISABLE_RECOVERY="true"
    # - 指定了菜单上文本显示的分辨率,它可以设置为你的显卡所支持的任何数值。
    GRUB_GFXMODE=1024x768
    复制

    Grub菜单启动项

      # 脚本的名称必须有两位的数字前缀。其目的是在构建 Grub 2 菜单时定义脚本的执行顺序以及相应菜单项的顺序
      [root@localhost ~]# ls /etc/grub.d/  | grep ''
      00_header : 首先被读取负责解析 /etc/default/grub 配置文件
      00_tuned
      01_users
      10_linux : 存放Linux 内核的菜单项,该脚本脚本在默认的 /boot 分区为每个内核创建一个正规菜单项和一个恢复菜单项
      20_linux_xen
      20_ppc_terminfo
      30_os-prober : 第三方应用所用脚本, 为内核和其它分区里的操作系统创建菜单项。它能识别安装的 Linux、 Windows、 BSD 以及 Mac OS X,如果你的硬盘布局比较独特使得 os-prober 无法找到已经安装的发行版你可以在 40_custom 文件进行设置;
      40_custom : 第三方应用所用脚本,到无法找到发行版时候需要添加自定义菜单项中;
      41_custom
      README
      复制

      2.2 启动阶段的精妙编排

      Stage 1:驻留在MBR的前446字节,负责加载Stage 1.5

      Stage 1.5:包含基础文件系统驱动,定位Stage 2

      Stage 2:完整的图形化界面和交互环境,加载操作系统内核

      2.3 配置文件的层次结构

      /boot/grub/grub.cfg作为核心配置文件,其生成过程体现分层设计理念:

        # 主配置文件(不建议直接修改)
        /etc/default/grub        # 基础参数设置
        /etc/grub.d/             # 模块化配置脚本目录
           00_header             # 核心参数
           10_linux              # 自动检测内核
           30_os-prober          # 多系统检测
        复制

        2.4 多系统检测机制

        通过os-prober模块自动扫描:

        Windows系统:识别NTFS分区的BCD存储

        macOS:检测APFS/HFS+分区

        其他Linux发行版:解析/boot目录

        三、实战配置指南

        3.1 基础参数调优

        编辑/etc/default/grub实现常用配置:

          GRUB_DEFAULT=0                         # 默认启动项序号
          GRUB_TIMEOUT=5                         # 等待时间(秒)
          GRUB_CMDLINE_LINUX="quiet splash"      # 内核参数
          GRUB_GFXMODE=1920x1080                 # 图形分辨率
          复制

          3.2 高级定制案例

          案例1:创建自定义启动项

            # 在/etc/grub.d/40_custom添加:
            menuentry "救援模式" {
                set root=(hd0,1)
                linux /vmlinuz rescue=1
                initrd /initrd.img
            }
            复制

            案例2:安全启动配置

              GRUB_PASSWORD=grub.pbkdf2.sha512.25000.ECD0A...  # 密码加密存储
              grub-mkpasswd-pbkdf2                  # 生成PBKDF2加密密码
              sudo grub-editenv - set password=xxx  # 设置环境变量密码
              复制
              3.3 配置更新流程
                sudo update-grub        # 生成新配置
                grub-install /dev/sda   # 安装到指定磁盘
                复制

                3.4 GRUB交互模式核心命令

                3.4.1 基础导航命令

                  ls                  # 列出所有可用存储设备
                  ls (hd0,gpt1)/      # 查看指定分区的文件系统
                  set root=(hd0,gpt2) # 设置根分区(UEFI系统示例)
                  复制

                  3.4.2 系统启动命令

                    linux /boot/vmlinuz-5.15.0-78-generic root=/dev/sda2  # 指定内核和根分区
                    initrd /boot/initrd.img-5.15.0-78-generic             # 加载初始化内存盘
                    boot                                                 # 执行启动
                    复制

                    3.4.3 故障诊断命令

                      lsmod               # 显示已加载模块
                      insmod ext2         # 加载文件系统模块
                      cat (hd0,1)/etc/os-release  # 查看系统信息
                      复制

                      3.5 高级调试命令集

                      3.5.1 内核参数调试

                        # 启动时按'e'编辑配置,添加:
                        systemd.debug-shell=1        # 启用调试Shell
                        acpi=off noapic nolapic      # 关闭高级电源管理
                        mem=4G                        # 限制内存使用
                        复制

                        3.5.2 磁盘阵列相关

                          mdadm --detail /boot/grub/device.map  # 查看磁盘映射
                          grub-probe --target=fs_uuid /boot     # 获取文件系统UUID
                          复制

                          3.5.3 网络启动命令

                            insmod net
                            insmod http
                            net_bootp
                            复制

                            四、故障排查与进阶技巧

                            4.1 常见问题解决方案

                            启动电脑后,当 GRUB 无法按照boot.img –> core.img –> /boot/grub/顺序执行时,会看到命令行界面,等待用户输入命令。此时可以通过输入 GRUB 内置的命令来修复 GRUB 引导。

                            由于boot.img是写在 MBR 中的,如果不能执行直接跟 GRUB 引导方式说再见了,所以执行boot.img一般没问题。boot.img不能识别任何文件系统,core.img的位置是硬编码进boot.img的,所以执行boot.img一般没问题。

                            Grub 2 引导问题会让系统处于几种不同状态, 当系统开机后本该显示 bootloader 菜单的地方会指示出系统的当前状态: 

                            (1) 如果 系统中止于 grub> 提示符 ,表明 Grub 2 模块已经被加载,但是找不到 grub.cfg 文件 

                            (2) 如果前是完全版的 Grub 2 命令行 shell看到的是  grub rescue>  提示符表明 bootloader 不能找到 Grub 2 模块或者找不到任何引导文件 

                            (3) 如果你的屏幕只显示 ‘GRUB’ 一词,表明 bootloader 找不到通常位于主引导记录里的最基本的信息。

                            因此,常见的引导问题集中在/boot/grub/,主要有两种对应有两种引导修复模式:

                            1) GRUB Rescue 模式是 GRUB 无法找到/boot分区,也就无法找到/boot/grub/。修复方法可以参考:

                            由于在rescue模式下,只有少量的基本命令可用,必须通过一定的操作才能加载正常模块,然后进入正常模式。

                            rescue模式下可使用的命令有:set,ls,insmod,root,prefix(设置启动路径)

                            先假设grub2的核心文件在(hd0,8)分区,再来看看怎样从 rescue模式进入从(hd0,8)启动的正常模式(normal)。

                            在 rescue模式下search命令不能用,对不清楚grub2文件处于哪个分区的,可以用ls命令查看,比如

                            ls (hd0,8)/ 查看(hd0,8)分区根目录,看看有没有boot文件夹

                            ls (hd0,8)/boot/ 查看(hd0,8)分区的/boot目录下文件

                            ls (hd0,8)/boot/grub/ 查看(hd0,8)分区/boot/grub目录下文件

                            通过文件查看,可以确定 grub2核心文件处于哪个分区,接下来就可以进行从rescue到normal的转变动作:

                            先 ls 看看分区,根据分区列表,猜下 / 分区的编号再 ls (hd0,x)/ 看分区目录下文件确定找到 / 分区,不对的话继续找。找到 / 分区的 (hd0,x) 继续

                              grub rescue>root=(hd0,x)
                              grub rescue>prefix=/boot/grub
                              grub rescue>set root=(hd0,x)
                              grub rescue>set prefix=(hd0,x)/boot/grub
                              grub rescue>insmod normal
                              rescue>normal -------->若出现启动菜单,按c进入命令行模式
                              rescue>linux /boot/vmlinuz-xxx-xxx root=/dev/sdax
                              rescue>initrd /boot/initrd.img-xxx-xxx
                              rescue>boot
                              复制

                              内核版本号 -xxx-xxx可以按Tab键查看后再手动补全。

                              2) Bootloader 急救:

                              通过使用 live CD 或者在 Grub 2 shell 中修正此类错误;

                              如果 grub2-install 命令不能正常运作,使得你无法引导进入 Linux ,你需要完整地重装以及重新配置 bootloader, 任何拥有 chroot 工具的 Linux live CD 都可以实现这个目的,不过需要确保 live 介质的系统架构和硬盘上系统的架构一致。

                              因此当你希望 chroot 到 64 位系统,你必须使用 amd64 live 发行版, 启动进入 live 发行版之后,首先需要检查机器上的分区;

                              Step 1.使用 fdisk -l 列出磁盘上所有分区,记录你想修复的 Grub 2 系统所在的分区。

                              Step 2.从安装在 /dev/sda5 中的发行版中恢复 bootloader 。启动终端使用如下命令挂载分区:sudo mount /dev/sda5 /mnt

                              Step 3.绑定Grub 2 bootloader 需要进入的目录,以便检测其它操作系统:

                                $ sudo mount --bind /dev /mnt/dev
                                $ sudo mount --bind /dev/pts /mnt/dev/pts
                                $ sudo mount --bind /proc /mnt/proc
                                $ sudo mount --bind /sys /mnt/sys
                                复制

                                Step 4.离开 live 环境进入安装在 /dev/sda5 分区中的发行版了,通过 chroot :

                                  $ sudo chroot /mnt /bin/bash  # 灵魂
                                  复制

                                  Step 5.现在可以安装、检测、以及升级 Grub 了,跟之前一样,使用下面的命令来重装 bootloader;

                                    sudo grub2-install /dev/sda
                                    sudo grub-mkconfig -o /boot/grub/grub.cfg # 同时生成引导配置
                                    复制

                                    Step 6.现在你就有了 Grub 2 的一份全新拷贝,罗列了机器上所有的操作系统和发行版。在重启电脑之前,你需要依次退出 chroot 系统卸载所有分区,然后在重新后bootloader将被修复, 如下所示:

                                      $ exit
                                      $ sudo umount /mnt/{sys,proc,dev/pts,dev,}
                                      $ sudo umount /mnt
                                      复制

                                      4.2 性能优化建议

                                      清理旧内核:sudo apt autoremove --purge

                                      压缩内核镜像:xz -9 /boot/vmlinuz-*

                                      禁用无用模块:GRUB_PRELOAD_MODULES="part_gpt ext2"

                                      4.3 视觉美化方案

                                      通过grub-customizer工具实现:

                                        sudo add-apt-repository ppa:danielrichter2007/grub-customizer
                                        sudo apt install grub-customizer
                                        复制
                                        支持主题安装、背景替换、字体调整等功能。
                                        4.4 修复UEFI引导丢失
                                          # 进入Live环境后执行:
                                          mount /dev/nvme0n1p2 /mnt
                                          mount /dev/nvme0n1p1 /mnt/boot/efi
                                          mount --bind /dev /mnt/dev
                                          chroot /mnt
                                          grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=ubuntu
                                          复制

                                          原理说明:

                                          通过完整的挂载链重建,确保EFI系统分区正确识别,--bootloader-id参数保持与固件记录的启动项名称一致

                                          掌握这些命令组合后,您将能够:

                                          快速诊断90%的引导故障

                                          灵活定制多系统启动环境

                                          实现企业级系统的批量部署

                                          完成硬件兼容性深度调试

                                          建议在测试环境验证关键操作后,再应用于生产系统。遇到复杂问题时,可通过grub> echo $?查看上条命令的返回值辅助诊断。

                                          五、未来发展趋势 
                                          随着UEFI Class 3规范的普及,GRUB正在向更安全的启动架构演进。新版本已支持TPM测量、Secure Boot密钥自动注册等功能。微软与Canonical联合开发的fwupd项目,更是将GRUB与固件更新深度整合,构建起完整的系统安全链条。

                                          文章转载自老柴杂货铺,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                                          评论