一、先理解 10_linux 的角色
GRUB 的最终配置文件是:
/boot/grub/grub.cfg
但这个文件不应该手动修改,因为每次执行:
sudo update-grub
都会重新生成它。
生成过程是:
/etc/grub.d/*
↓
脚本执行
↓
拼接输出
↓
/boot/grub/grub.cfg
也就是说:
10_linux = 生成 Linux 启动菜单的脚本
GRUB 菜单是怎么生成的
核心流程是:
扫描 /boot/vmlinuz-*
↓
每个内核调用 linux_entry()
↓
linux_entry() 生成 menuentry
↓
写入 grub.cfg
也就是说:
每个 kernel → 一个 menuentry
例如最终生成:
menuentry 'Ubuntu'
menuentry 'Ubuntu, with Linux 6.8.0-88-generic'
menuentry 'Ubuntu, with Linux 6.8.0-88-generic (recovery mode)'
最关键的函数:linux_entry()
在 10_linux 里有一个核心函数:
linux_entry ()
它负责:
生成一个 GRUB menuentry
函数定义:
linux_entry ()
{
os="$1"
version="$2"
type="$3"
args="$4"
}
参数含义:
| 参数 | 含义 |
|---|---|
$1 | 操作系统名 |
$2 | 内核版本 |
$3 | 启动类型 |
$4 | 启动参数 |
type 是整个逻辑的核心
type 有三种:
| type | 菜单 |
|---|---|
| simple | 顶层 Ubuntu |
| advanced | Advanced options 里的普通内核 |
| recovery | recovery mode |
举例:
simple
Ubuntu
advanced
Ubuntu, with Linux 6.8.0
recovery
Ubuntu, with Linux 6.8.0 (recovery mode)
原始 10_linux 的逻辑
原版代码是:
if [ x$type != xsimple ] ; then
意思:
如果不是 simple
也就是:
advanced 或 recovery
然后生成标题:
case $type in
recovery)
title="Ubuntu, with Linux 6.x (recovery mode)"
;;
*)
title="Ubuntu, with Linux 6.x"
;;
esac
然后生成 GRUB 菜单:
echo "menuentry 'TITLE' ..."
例如最终写入:
menuentry 'Ubuntu, with Linux 6.8.0-88-generic' ...
我改的是:
menuentry 生成逻辑
也就是这行:
echo "menuentry ..."
把它拆成:
recovery
普通启动
两种情况。
加入权限控制
新增了:
case $type in
recovery)
echo "menuentry ... "
;;
*)
echo "menuentry ... --unrestricted"
;;
esac
逻辑变成:
如果是 recovery
不加 unrestricted
否则
加 unrestricted
--unrestricted 的作用
GRUB 的规则是:
如果存在:
set superusers="admin"
那么:
所有 menuentry 默认需要认证
除非:
--unrestricted
所以:
| 菜单 | 权限 |
|---|---|
| 普通启动 | unrestricted |
| recovery | 需要认证 |
simple 启动项
simple 生成代码:
echo "menuentry 'Ubuntu' ..."
改成:
echo "menuentry 'Ubuntu' ... --unrestricted"
意思:
默认 Ubuntu 启动免密码
完整逻辑图
现在整个逻辑变成:
扫描 kernel
↓
调用 linux_entry()
↓
判断 type
↓
+--------------------+
| simple |
| → unrestricted |
+--------------------++
| advanced |
| → unrestricted |
+--------------------++
| recovery |
| → 需要认证 |
+--------------------+
最终生成的 grub.cfg
生成的内容类似:
menuentry 'Ubuntu' --unrestricted
menuentry 'Ubuntu, with Linux 6.8' --unrestricted
menuentry 'Ubuntu, with Linux 6.8 (recovery mode)'
为什么 e 会要求密码?
没有专门保护 e。
但 GRUB 的规则是:
如果存在:
superusers
那么:
| 操作 | 权限 |
|---|---|
| 编辑 menuentry | 需要认证 |
| GRUB shell | 需要认证 |
| 非 unrestricted menuentry | 需要认证 |
所以:
按 e → 要密码
为什么 01_users 必须 chmod
因为:
/etc/grub.d/*
里面的文件只有 可执行脚本 才会执行。
如果:
-rw-r--r--
就不会执行。
所以:
chmod 755
非常关键。
Comments NOTHING