在CentOS/RHEL 7和8中更新和重建initrd镜像的2种方法

时间:2020-02-23 14:40:39  来源:igfitidea点击:

如何解压缩或者解压缩initrd或者initramfs引导镜像文件?
如何修改initrd或者initramfs的内容?
如何查看initrd或者initramfs?
如何在RHEL Linux中自定义initrd。
如何在RHEL 8 Linux中重建initrd镜像。
如何在RHEL 7 Linux中更新initrd。
如何使用XV压缩数据更新initrd。
如何使用LZMA压缩数据重建initrd镜像。
如何在Red Hat Enterprise Linux中重建初始ramdisk镜像。
如何在Red Hat Enterprise Linux中重建初始ram磁盘镜像。
如何重制或者重新创建initrd或者initramfs。

什么是initrd?

  • 初始RAM磁盘(initrd)是在实际根文件系统可用之前已安装的初始根文件系统。
    initrd绑定到内核,并作为内核引导过程的一部分进行加载。
    然后,内核将此initrd挂载为两阶段引导过程的一部分,以加载模块以使实际文件系统可用并获得真实的根文件系统。

  • initrd文件包含用于实现此目的的最少目录和可执行文件集,例如用于将内核模块安装到内核中的" insmod"工具。
    换句话说,它包含必要的可执行文件和系统文件,以支持Linux系统的第二阶段引导。

  • initrd镜像位于/boot目录下,并由内核软件包拥有。

  • 系统上正在运行的内核的版本将用于识别引导过程中使用的当前initrd镜像。

提示:

RHEL 7提供了两个initrd镜像。
一个是在内核安装到根文件系统上之后创建的,即在/boot/initramfs-$(uname -r).img中可用,而另一个在在系统启动的初始阶段加载的RHEL ISO DVD。
在本文中,我们研究了RHEL ISO DVD中提供的更新和重建initrd的步骤,以了解从系统中提取和重建initramfs的步骤,我们可以按照本文进行操作。

为什么要更新initrd?

Initrd包含许多用于第三方供应商的驱动程序,以及许多有助于操作系统检测底层硬件的模块和可执行文件。
在新硬件上,initrd可能无法检测到底层硬件部件,例如网卡,存储适配器等。
在这种情况下,我们可以修改" initrd"镜像。

尽管不建议将第三方供应商的驱动程序模块添加到initrd中,但我还是建议创建一个自定义DUD(驱动程序更新磁盘),因为它也执行相同的任务,并且比更新和重建initrd更好。

说明:

不建议在生产环境中修改" initrd",如果我们具有有效的订阅,则应与支持团队联系以处理需要修改" initrd"的任何问题。

除了修改initrd镜像外,我们还可以选择创建一个updates.img文件,该文件在BOOT UP的稍后阶段被调用。
但是,如果问题与底层硬件的检测失败有关,那么" updates.img"将无济于事。

选择哪一个initrd.img还是updates.img?

anaconda可以在运行时合并更新,以修复安装程序中的所有错误或者问题。
这些更新通常作为磁盘镜像文件分发(在本文中称为updates.img)。

因此,我们有两个选项可以通过自定义更改来更改启动过程,一个选项使用initrd,另一个选项使用updates.img

这个问题的答案取决于要求。
在启动过程的后期会调用updates.img,因此,如果我们希望包括重要的模块来检测硬件,则应该更新并重建initrd,而如果需要为RHEL OS添加一些错误修复,则继续updates.img

检查initrd内容

在更新initrd之前,最好验证一下initrd镜像的现有内容。
其中我正在从RHEL 8 ISO镜像检查initrd的内容。

[root@rhel-8 ~]# lsinitrd /mnt/images/pxeboot/initrd.img  | less
Image: /mnt/images/pxeboot/initrd.img: 58M
========================================================================
Version: dracut-049-10.git20190115.el8
Arguments: --nomdadmconf --nolvmconf --xz --install '/.buildstamp' --no-early-microcode --add 'fips' --add 'anaconda pollcdrom qemu qemu-net prefixdevname-tools' --force
dracut modules:
bash
systemd
fips
systemd-initrd
modsign
nss-softokn
i18n
convertfs
network-legacy
network
ifcfg
url-lib
drm
plymouth
<Output trimmed>
drwxr-xr-x   2 root     root            0 Jan 15  2019 var/lib/nfs/rpc_pipefs
drwxrwxr-x   3 root     root            0 Jan 15  2019 var/lib/nfs/statd
drwxr-xr-x   2 root     root            0 Jan 15  2019 var/lib/nfs/statd/sm
drwxrwx---   2 root     root            0 Jan 15  2019 var/lib/rpcbind
lrwxrwxrwx   1 root     root           11 Jan 15  2019 var/lock -> ../run/lock
lrwxrwxrwx   1 root     root            6 Jan 15  2019 var/run -> ../run
drwxr-xr-x   2 root     root            0 Jan 15  2019 var/tmp
========================================================================

在此列表中,我们可以其中查找initrd图像文件的内容。

方法1:提取initrd图像

根据initrd文件压缩类型,提取和重建initrd的命令将有所不同。
对于RHEL 7和8中的情况,我们在initrd文件中具有XZ压缩数据,如下所示:

[root@rhel-8 ~]# file /mnt/images/pxeboot/initrd.img
/mnt/images/pxeboot/initrd.img: XZ compressed data
[root@rhel-8 ~]# cat /etc/redhat-release
Red Hat Enterprise Linux release 8.0 (Ootpa)
[root@rhel-7 ~]# file /mnt/images/pxeboot/initrd.img
/mnt/images/pxeboot/initrd.img: XZ compressed data
[root@rhel-7 ~]# cat /etc/redhat-release
Red Hat Enterprise Linux Server release 7.6 (Maipo)

因此,我们可以使用相同的方法为RHEL 7和8 Linux提取并重建initrd。

重要的提示:

提取initrd之前,请确保已备份initrd文件,或者可以在不触摸原始文件的情况下提取到其他位置。

我们将创建一个临时目录,其中提取和更新initrd

[root@rhel-8 custom_initrd]# mkdir /tmp/custom_initrd

要提取initrd,请使用以下命令:

[root@rhel-8 custom_initrd]# xz -dc < /mnt/images/pxeboot/initrd.img | cpio -idmv

这将提取当前目录中initrd的所有内容

[root@rhel-8 custom_initrd]# ls -l
total 44
lrwxrwxrwx.  1 root root    7 Sep 13 19:44 bin -> usr/bin
drwxr-xr-x.  2 root root 4096 Sep 13 19:44 dev
drwxr-xr-x. 14 root root 4096 Sep 13 19:44 etc
lrwxrwxrwx.  1 root root   23 Sep 13 19:44 init -> usr/lib/systemd/systemd
lrwxrwxrwx.  1 root root    7 Sep 13 19:44 lib -> usr/lib
lrwxrwxrwx.  1 root root    9 Sep 13 19:44 lib64 -> usr/lib64
drwxr-xr-x.  2 root root 4096 Jan 15  2019 proc
drwxr-xr-x.  2 root root 4096 Jan 15  2019 root
drwxr-xr-x.  2 root root 4096 Jan 15  2019 run
lrwxrwxrwx.  1 root root    8 Sep 13 19:44 sbin -> usr/sbin
-rwxr-xr-x.  1 root root 3126 Oct  8  2016 shutdown
drwxr-xr-x.  2 root root 4096 Jan 15  2019 sys
drwxr-xr-x.  2 root root 4096 Jan 15  2019 sysroot
drwxrwxr-x.  2 root root 4096 Jan 15  2019 tmp
drwxrwxr-x.  9 root root 4096 Sep 13 19:44 usr
drwxr-xr-x.  4 root root 4096 Sep 13 19:44 var

方法2:提取initrd图像

另外,我们也可以使用以下步骤列表提取initrd。
首先将initrd文件从RHEL 7/8 ISO DVD复制到临时目录

[root@rhel-8 custom_initrd]# cp /mnt/isolinux/initrd.img /tmp/custom_initrd/

验证文件

[root@rhel-8 custom_initrd]# ls -lh
total 58M
-r--r--r--. 1 root root 58M Sep 13 22:03 initrd.img

现在解压缩文件

[root@rhel-8 custom_initrd]# unxz -S .img initrd.img

这样,initrd.img将提取并创建一个initrd文件

[root@rhel-8 custom_initrd]# ls -lh
total 171M
-r--r--r--. 1 root root 185M Sep 13 22:03 initrd

将initrd的内容提取到当前目录中

[root@rhel-8 custom_initrd]# cat initrd | cpio -idm
cpio: .buildstamp not created: newer or same age version exists
378442 blocks

验证initrd的内容

[root@rhel-8 custom_initrd]# ls -lh
total 171M
lrwxrwxrwx.  1 root root    7 Sep 13 22:07 bin -> usr/bin
drwxr-xr-x.  2 root root 4.0K Sep 13 22:07 dev
drwxr-xr-x. 14 root root 4.0K Sep 13 22:07 etc
lrwxrwxrwx.  1 root root   23 Sep 13 22:07 init -> usr/lib/systemd/systemd
-r--r--r--.  1 root root 185M Sep 13 22:03 initrd
lrwxrwxrwx.  1 root root    7 Sep 13 22:07 lib -> usr/lib
lrwxrwxrwx.  1 root root    9 Sep 13 22:07 lib64 -> usr/lib64
drwxr-xr-x.  2 root root 4.0K Jan 15  2019 proc
drwxr-xr-x.  2 root root 4.0K Jan 15  2019 root
drwxr-xr-x.  2 root root 4.0K Jan 15  2019 run
lrwxrwxrwx.  1 root root    8 Sep 13 22:07 sbin -> usr/sbin
-rwxr-xr-x.  1 root root 3.1K Oct  8  2016 shutdown
drwxr-xr-x.  2 root root 4.0K Jan 15  2019 sys
drwxr-xr-x.  2 root root 4.0K Jan 15  2019 sysroot
drwxrwxr-x.  2 root root 4.0K Jan 15  2019 tmp
drwxrwxr-x.  9 root root 4.0K Sep 13 22:07 usr
drwxr-xr-x.  4 root root 4.0K Sep 13 22:07 var

更新initrd镜像

现在,由于我们已经成功提取了initrd,因此我们可以继续进行修改。
例如,我们可以从供应商处添加新的驱动程序模块,以支持某些新硬件或者任何其他自定义更改。

重要的提示:

不要更改initrd镜像的目录结构

为了本文的方便,我希望将一个udev规则文件添加到initrd中,以检测和映射具有预定义PCI ID的NIC卡。

# cat 20-persistent-net.rules
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", BUS=="pci", ID=="0000:01:00.0", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", BUS=="pci", ID=="0000:01:00.1", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth1"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", BUS=="pci", ID=="0000:03:00.0", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth2"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", BUS=="pci", ID=="0000:03:00.1", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth3"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", BUS=="pci", ID=="0000:04:00.0", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth4"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", BUS=="pci", ID=="0000:04:00.1", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="eth5"

我们将其添加到initrd中的/usr/lib/udev/rules.d下。

[root@rhel-8 rules.d]# ls -l
total 124
-r--r--r--. 1 root root 7266 Jan 15  2019 10-dm.rules
-r--r--r--. 1 root root 2454 Jan 15  2019 11-dm-lvm.rules
-rw-r--r--. 1 root root 4538 Jan 15  2019 11-dm-mpath.rules
-r--r--r--. 1 root root 1794 Jan 15  2019 13-dm-disk.rules
-rw-r--r--. 1 root root  876 Sep 13 20:13 20-persistent-net.rules
-rw-r--r--. 1 root root 1622 Jan 15  2019 40-redhat.rules
-rw-r--r--. 1 root root 3679 Jan 15  2019 50-udev-default.rules

方法1:重建initrd镜像

如果我们使用方法1提取initrd,然后按照以下步骤重建initrd镜像,请导航到提取了initrd镜像的临时目录。

[root@rhel-8 rules.d]# cd /tmp/custom_initrd/
[root@rhel-8 custom_initrd]#

执行以下命令以xz作为压缩格式重建initrd镜像

[root@rhel-8 custom_initrd]# find . 2>/dev/null | cpio -c -o | xz -9 --format=xz > /tmp/new.img
378439 blocks

检查新initrd文件的压缩类型

[root@rhel-8 custom_initrd]# ls -l /tmp/new.img
-rw-r--r--. 1 root root 53615972 Sep 13 20:24 /tmp/new.img
[root@rhel-8 custom_initrd]# file /tmp/new.img
/tmp/new.img: XZ compressed data

方法2:重建initrd镜像

如果我们使用方法2执行解压缩initrd,然后按照以下步骤重建initrd镜像,请导航到提取initrd镜像的临时目录。

删除已解压缩的initrd文件在同一目录中。

[root@rhel-8 custom_initrd]# rm -f initrd

接下来使用以下命令重建initrd镜像:

[root@rhel-8 custom_initrd]# find . | cpio -oc > ../initrd; cd ..; xz -S .img initrd
378442 blocks

验证新的initrd镜像

[root@rhel-8 tmp]# ls -lh initrd.img
-rw-r--r--. 1 root root 53M Sep 13 22:15 initrd.img

验证initrd镜像

现在,既然我们成功地重建了initrd镜像,那么让我们验证新initrd的内容,并确保新的规则文件存在于该initrd镜像中

[root@rhel-8 custom_initrd]# lsinitrd  /tmp/new.img | grep 20-persistent-net.rules
-rw-r--r--   1 root     root          876 Sep 13 20:13 usr/lib/udev/rules.d/20-persistent-net.rules

如我们所见,我们的文件现在是initrd文件的一部分。
因此,现在我们可以使用此initrd文件启动系统。

同样,我们可以验证使用方法2创建的initrd的内容。