CentOS 7 是否对 grub.cfg 中的内核菜单条目进行了错误排序?

CentOS 7 是否对 grub.cfg 中的内核菜单条目进行了错误排序?

我注意到 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

这是一个众所周知的错误:

要确定内核包如何更新,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

相关内容