RHEL从8版本开始,内核包安装不再单纯依赖grubby或mkinitrd,而是统一交给systemd提供的kernel-install框架。该框架会在/usr/lib/kernel/install.d和/etc/kernel/install.d两个目录中按文件名顺序执行所有可执行脚本,完成内核映像复制、initramfs生成、引导加载器条目创建以及旧内核清理等任务。故障发生时,往往表现为dnf事务报错、新内核无法出现在启动菜单,或者/boot目录下缺少对应initramfs文件。本文将围绕这套插件机制,说明如何从日志和退出码入手,准确找到问题插件并完成修复。

在实际运维中,很多看似复杂的内核安装失败,最终都能追溯到某个插件脚本的细微错误。理解执行链的顺序和返回值传递规则,是快速定位问题的关键。
一、理解kernel-install插件的执行链与故障表现
kernel-install的设计目标是把不同发行版的内核安装流程标准化。它执行一个命令时,会先读取/etc/kernel/install.conf配置文件,随后按照文件名排序依次执行/usr/lib/kernel/install.d目录下的脚本,再执行/etc/kernel/install.d目录下的同名或追加脚本。管理员自定义的脚本应放在/etc/kernel/install.d中,这样可以覆盖发行版默认行为。
每个插件脚本会接收三个核心参数:内核版本号、内核映像的绝对路径、以及安装目录。例如执行kernel-install add 5.14.0-362.8.1.el9_3.x86_64 /boot/vmlinuz-5.14.0-362.8.1.el9_3.x86_64时,第一个参数就是版本号,第二个参数是vmlinuz文件路径。插件可以读取这些参数来完成自己的工作,例如dracut插件根据版本号生成对应的initramfs,loaderentry插件调用grubby写入启动菜单。
故障最典型的表现是dnf update命令在安装内核RPM包时卡住或直接报错,错误信息中可能包含类似scriptlet failed、exit code 1等字样。有时更新看似成功,但重启后新内核没有出现在GRUB菜单,或者选中新内核后无法挂载initramfs。出现这些现象时,就应该怀疑kernel-install的插件链没有完整执行。
二、从日志与手动执行中定位问题插件
定位问题的第一步是查看journalctl中关于内核安装脚本的输出。systemd会记录软件包脚本的执行过程,使用如下命令可以过滤出相关日志:
journalctl -b | grep -i kernel-install journalctl -u systemd-udevd -b | grep -i kernel-install
如果日志不够详细,可以在执行kernel-install命令前设置环境变量KERNEL_INSTALL_VERBOSE=1,这样每个插件在执行时会打印更多调试信息,包括它接收的参数和每一步操作。手动执行命令的语法如下:
KERNEL_INSTALL_VERBOSE=1 kernel-install add 5.14.0-362.8.1.el9_3.x86_64 /boot/vmlinuz-5.14.0-362.8.1.el9_3.x86_64
执行后要特别注意每个插件名称后面的返回值。正常的插件应当在结束时返回0。如果某个脚本返回非零值,kernel-install会立即停止后续插件执行,并在终端显示类似plugin /etc/kernel/install.d/50-dracut.install failed with exit code 1的提示。根据这个脚本名称,就能把范围缩小到具体的插件。
如果没有明显的错误输出,可以逐个隔离插件测试。方法是临时把/usr/lib/kernel/install.d或/etc/kernel/install.d目录中可疑的脚本移走或重命名,然后重新执行kernel-install add命令。如果移除某个脚本后流程顺利完成,说明问题就出在这个脚本内部。比较常见的隐藏错误是脚本没有可执行权限,或者脚本第一行缺少正确的shebang,导致解释器无法执行。
三、修复常见插件故障与编写自定义插件规范
权限问题是最容易修复的故障。检查插件脚本是否具有可执行权限,使用ls -l /etc/kernel/install.d/查看。如果自定义脚本权限为644,kernel-install会跳过它,但某些情况下会因为预期执行失败而报错。修复命令非常简单:
chmod +x /etc/kernel/install.d/99-custom-log.install
另一个高频错误是脚本内部调用了不存在的命令,或者命令执行后返回非零值而没有进行捕获。例如脚本中写了一条grub2-mkconfig -o /boot/grub2/grub.cfg,如果/boot分区空间不足导致写入失败,脚本会返回非零,从而中断整个内核安装。对于自定义插件,必须保持一个原则:无论内部某个命令是否成功,最后都要显式返回0,除非确实需要让内核安装失败。下面是一个安全的自定义插件示例,它只记录日志而不干扰安装流程:
#!/bin/bash # /etc/kernel/install.d/99-custom-log.install LOG=/var/log/kernel-install-custom.log echo plugin called with version $1 >> $LOG exit 0
注意上面脚本中重定向符号>>在HTML代码块中已经转义,实际使用时保持原样即可。创建完成后记得执行chmod +x。如果插件需要实现一些核心功能,例如在安装新内核后自动清理旧的DKMS模块,应当使用set -e来及时捕获错误,并在脚本末尾显式返回0。同时建议把错误输出重定向到独立日志文件,方便事后排查。
还要检查/etc/kernel/install.conf文件格式。该文件采用KEY=value形式,如果出现重复键或非法字符,会导致kernel-install读取配置失败。常见错误是把路径写成BOOT_ROOT=/boot 时不小心多了一个空格,虽然大部分解析器会忽略,但严格环境下会报错。建议保持配置简洁,并定期备份。
四、恢复中断的内核安装与日常预防
当某个插件失败导致新内核只安装了一半时,/boot目录可能已经存在vmlinuz文件,但缺少对应的initramfs,或者GRUB菜单中没有条目。此时不要直接再次运行dnf update,因为残留文件可能让后续操作更混乱。正确的做法是先用kernel-install remove清理残留,再重新执行kernel-install add:
kernel-install remove 5.14.0-362.8.1.el9_3.x86_64 /boot/vmlinuz-5.14.0-362.8.1.el9_3.x86_64 kernel-install add 5.14.0-362.8.1.el9_3.x86_64 /boot/vmlinuz-5.14.0-362.8.1.el9_3.x86_64
如果remove命令也报错,可以手动删除/boot下与该版本相关的文件,但删除前务必确认没有误删其他正在使用的内核。之后重新运行add命令,观察每个插件是否正常返回0。修复完成后,建议执行grubby --info=ALL或查看/boot/loader/entries目录,确认新内核条目已经生成。
预防方面,所有自定义插件都应纳入版本控制,并在测试环境充分验证后再下发到生产服务器。建议在插件脚本开头增加日志输出,并把退出码规则写入团队文档。定期检查/etc/kernel/install.d目录中的文件权限和内容变化,防止误操作或安全风险。通过建立这些规范,RHEL的内核更新流程可以保持稳定,kernel-install插件故障也能在极短时间内定位和修复。
RHELkernel-install插件故障处理修改时间:2026-08-24 04:15:38