我正在运行 ubuntu 20.04,安装了许多内核,从默认内核到我在本地编译的自定义内核。当我运行时sudo update-grub
,我当前正在摆弄的内核(即上次编译的内核)总是被神奇地选为启动的默认选项。
这是如何工作的?update-grub 如何知道应该将哪个内核设置为默认内核?我发现文档关于这个话题的评论令人恼火地贫乏:
它的工作原理是在 /boot 中查找所有以“vmlinuz-”开头的文件。这些文件将被视为内核,并为每个文件创建 grub 菜单条目。
这很好,但是如何?
答案1
update-grub
调用grub-mkconfig
,后者又运行 中的 shell 脚本/etc/grub.d
。其中之一是/etc/grub.d/10_linux
,它使用 shell 函数version_find_latest
不断迭代剩余 Linux 内核列表,从最新到最旧。
shell 函数version_find_latest
在 中定义/usr/share/grub/grub-mkconfig_lib
,使用辅助函数version_test_gt
(也在同一文件中定义)。此函数使用 sed 正则表达式的混合来检测预发布版本、git 版本等,最后求助于 来dpkg --compare-versions
比较两个点修订字符串。
您实际上可以在 shell 中尝试它,而无需编译任何内核或更改任何 grub 配置:
$ source /usr/share/grub/grub-mkconfig_lib
$ version_find_latest vmlinuz-5.6.7-aaa vmlinuz-5.1.12 vmlinuz-5.6.7-git
vmlinuz-5.6.7-aaa
答案2
这不是一个权威的答案,如果有更好的答案,它将被删除。
grub 菜单上的内核顺序主要按版本排序。但是 grub 似乎知道发布候选版本和最终版本之间的区别。除了“.”之外,它似乎还将“-”字符视为分隔符。
示例(经过编辑,之后grep menuentry /boot/grub.cfg
):
menuentry 'Ubuntu, with Linux 5.8.0-050800-lowlatency' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.8.0-050800-lowlaten>
menuentry 'Ubuntu, with Linux 5.8.0-050800-lowlatency (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.8.0>
menuentry 'Ubuntu, with Linux 5.8.0-rc1-qp-sp-ps2' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.8.0-rc1-qp-sp-ps2-advan>
menuentry 'Ubuntu, with Linux 5.8.0-rc1-qp-sp-ps2 (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.8.0-rc1>
menuentry 'Ubuntu, with Linux 5.8.0-rc1-qp-sp-powersave' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.8.0-rc1-qp-sp-pow>
menuentry 'Ubuntu, with Linux 5.8.0-rc1-qp-sp-powersave (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.8>
menuentry 'Ubuntu, with Linux 5.8.0-rc1-qp-sp' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.8.0-rc1-qp-sp-advanced-0ac3>
menuentry 'Ubuntu, with Linux 5.8.0-rc1-qp-sp (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.8.0-rc1-qp->
menuentry 'Ubuntu, with Linux 5.8.0-rc1-stock' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.8.0-rc1-stock-advanced-0ac3>
menuentry 'Ubuntu, with Linux 5.8.0-rc1-stock (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.8.0-rc1-sto>
menuentry 'Ubuntu, with Linux 5.8.0-rc1-spv2' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.8.0-rc1-spv2-advanced-0ac356>
menuentry 'Ubuntu, with Linux 5.8.0-rc1-spv2 (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.8.0-rc1-spv2>
menuentry 'Ubuntu, with Linux 5.8.0-rc1-ds4' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.8.0-rc1-ds4-advanced-0ac356c1>
menuentry 'Ubuntu, with Linux 5.8.0-rc1-ds4 (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.8.0-rc1-ds4-r>
menuentry 'Ubuntu, with Linux 5.8.0-rc1-ds3' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.8.0-rc1-ds3-advanced-0ac356c1>
menuentry 'Ubuntu, with Linux 5.8.0-rc1-ds3 (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.8.0-rc1-ds3-r>
menuentry 'Ubuntu, with Linux 5.8.0-rc1-ds1' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.8.0-rc1-ds1-advanced-0ac356c1>
menuentry 'Ubuntu, with Linux 5.8.0-rc1-ds1 (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.8.0-rc1-ds1-r>
menuentry 'Ubuntu, with Linux 5.7.0-doug-hwp' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.7.0-doug-hwp-advanced-0ac356>
menuentry 'Ubuntu, with Linux 5.7.0-doug-hwp (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.7.0-doug-hwp>
menuentry 'Ubuntu, with Linux 5.7.0-050700rc6-lowlatency' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.7.0-050700rc6-lo>
menuentry 'Ubuntu, with Linux 5.7.0-050700rc6-lowlatency (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.>
menuentry 'Ubuntu, with Linux 5.7.0-050700rc3-lowlatency' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.7.0-050700rc3-lo>
menuentry 'Ubuntu, with Linux 5.7.0-050700rc3-lowlatency (recovery mode)' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.>
...
上面的列表中5.8.0-rc1-ds4
实际上是最近编译的,但在列表中排在第 7 位。列表中的第一个实际上是来自主线 PPA 的 rc1,文件名不正确,因为它实际上是 -rc1。这个5.8.0-rc1-qp-sp-ps2
实际上相当旧,我认为是额外的“-”分隔符导致了它在列表中的位置。