我注意到 CentOS 7 系统上的 grub 菜单项的顺序出现意外:
它安装了以下内核:
$ ls /boot/vmlinuz* -ltr
Jun 30 14:17 /boot/vmlinuz-3.10.0-123.el7.x86_64
Nov 6 16:14 /boot/vmlinuz-3.10.0-123.9.3.el7.x86_64
Nov 23 17:12 /boot/vmlinuz-0-rescue-c61cbe0918ab45e0927fb5d31cf45f98
在我对版本方案的解释中,版本“3.10.0-123.9.3.el7”大于“3.10.0-123.el7”。这也与文件 mtime 一致 - 并且也与uname -a
输出匹配:
3.10.0-123.el7.x86_64 Mon Jun 30 12:09:22 UTC 2014
3.10.0-123.9.3.el7.x86_64 Thu Nov 6 15:06:03 UTC 2014
但/boot/grub2/grub.cfg
使用另一个命令:
$ grep vmlinuz-3 /boot/grub2/grub.cfg | sed 's/root=.*//'
linux16 /vmlinuz-3.10.0-123.el7.x86_64
linux16 /vmlinuz-3.10.0-123.9.3.el7.x86_64
啊?
由于系统获得了一些额外的内核参数,因此grub.cfg
通过以下命令显式重新生成:
# grub2-mkconfig -o /boot/grub2/grub.cfg
哪个应该是官方方法- 如手册中所述。
该排序显然是通过以下方式实现的:
/etc/grub.d/10_linux
-> /usr/share/grub/grub-mkconfig_lib
-> version_find_latest()
-> version_test_gt()
这是 grub2-mkconfig 中众所周知的错误吗?
不过,我找不到它的错误报告。
令人惊讶的是,在另一台 CentOS 7 机器(也是最新的)上,grub.cfg 顺序是正确的:
$ grep vmlinuz /boot/efi/EFI/centos/grub.cfg | sed 's/root=.*//'
linuxefi /vmlinuz-3.10.0-123.9.3.el7.x86_64
linuxefi /vmlinuz-3.10.0-123.9.2.el7.x86_64
linuxefi /vmlinuz-3.10.0-123.8.1.el7.x86_64
linuxefi /vmlinuz-3.10.0-123.6.3.el7.x86_64
linuxefi /vmlinuz-3.10.0-123.el7.x86_64
linuxefi /vmlinuz-0-rescue-48235f1ad5c943c3a7dfd1551a1fc5b8
两台机器之间的区别是:在第二台机器上grub2-mkconfig
从未手动执行过。
事实上,当手动执行它时,顺序也是错误的:
# grub2-mkconfig -o del.cfg
# grep vmlinuz del.cfg | sed 's/root=.*//'
linuxefi /vmlinuz-3.10.0-123.el7.x86_64
linuxefi /vmlinuz-3.10.0-123.9.3.el7.x86_64
linuxefi /vmlinuz-3.10.0-123.9.2.el7.x86_64
linuxefi /vmlinuz-3.10.0-123.8.1.el7.x86_64
linuxefi /vmlinuz-3.10.0-123.6.3.el7.x86_64
linuxefi /vmlinuz-0-rescue-48235f1ad5c943c3a7dfd1551a1fc5b8
因此,看起来,当通过安装内核更新时yum update
,安装脚本不会执行grub-2-mkconfig -o /boot/efi/EFI/centos/grub.cfg
.grub.cfg
那么在内核包安装期间如何重新生成呢?
答案1
这是一个众所周知的错误:
- grub2-mkconfig 以错误的顺序创建引导选项(CentOS Bug 0007651)
- grub2-mkconfig 排序错误(RHEL Bug 1124074)
- grub2 错误排序(错误 678840 - 已修复)
要确定内核包如何更新,grub.cfg
可以通过以下方式显示脚本:
$ yum whatprovides /boot/vmlinuz-3.10.0-123.9.3.el7.x86_64
kernel-3.10.0-123.9.3.el7.x86_64 : The Linux kernel
[..]
$ rpm -q --scripts kernel-3.10.0-123.9.3.el7.x86_64
这表明被/usr/sbin/new-kernel-pkg
调用 - 依次调用肮脏的。
解决方法
(直到在 RHEL/CentOS 中修复为止)
--- /usr/share/grub/grub-mkconfig_lib.orig 2014-06-30 18:16:11.000000000 +0200 +++ /usr/share/grub/grub-mkconfig_lib 2014-11-26 17:38:57.814000000 +0100 @@ -255,13 +255,24 @@ 版本_查找_最新() { - version_find_latest_a="" - 对于“$@”中的 i ;做 - 如果 version_test_gt "$i" "$version_find_latest_a" ;然后 - version_find_latest_a="$i" -fi - 完毕 - 回显“$version_find_latest_a” + # https://bugzilla.redhat.com/show_bug.cgi?id=1124074 的解决方法 + # 'grub2-mkconfig 排序错误' + { + 对于“$@”中的 i;做 + 回显 $i + 完成 | grep -v 救援 |排序-V + 对于“$@”中的 i;做 + 回显 $i + 完成 | grep 救援 |排序-V + } |头-n 1 }
答案2
我发布了两个 bugzilla.redhat.com 错误的补丁,实际上解决了这个问题。 maxschlepzig 的补丁非常接近正确答案,但又不完全是。我的补丁是基于他的。
答案3
我认为您确定安装内核后发生的情况的方法如下使用rpm
+--scripts
开关。
例子
$ rpm --scripts -q kernel-$(uname -r)
postinstall scriptlet (using /bin/sh):
if [ `uname -i` == "x86_64" -o `uname -i` == "i386" ] &&
[ -f /etc/sysconfig/kernel ]; then
/bin/sed -r -i -e 's/^DEFAULTKERNEL=kernel-smp$/DEFAULTKERNEL=kernel/' /etc/sysconfig/kernel || exit $?
fi
preuninstall scriptlet (using /bin/sh):
/bin/kernel-install remove 3.16.6-203.fc20.x86_64 /boot/vmlinuz-3.16.6-203.fc20.x86_64 || exit $?
posttrans scriptlet (using /bin/sh):
/bin/kernel-install add 3.16.6-203.fc20.x86_64 /boot/vmlinuz-3.16.6-203.fc20.x86_64 || exit $?
这分为几个部分:安装后,预卸载, 和邮递员。执行内核安装/删除的工具是以下脚本:
/bin/kernel-install add <kernel label> </path/to/boot/vmlinuz-...> || exit $
谁拥有这个脚本?
该脚本kernel-install
是 Systemd 的一部分。
$ rpm -qf /bin/kernel-install
systemd-208-28.fc20.x86_64