dracut或mkinitcpio,但了解mkinitrd对于维护旧系统仍有价值。
mkinitrd用于创建初始RAM磁盘(initrd)映像文件。initrd是一个临时的根文件系统,在Linux内核启动过程中被加载到内存中,用于加载必要的硬件驱动和模块,然后挂载真正的根文件系统。它是系统启动过程中的关键组件。
mkinitrd [选项] 映像文件 内核版本
| 选项 | 说明 |
|---|---|
-f |
强制覆盖现有映像文件 |
--preload 模块 |
预加载指定的内核模块 |
--omit-scsi-modules |
省略SCSI模块 |
--omit-raid-modules |
省略RAID模块 | --omit-lvm-modules |
省略LVM模块 |
--with 模块 |
包含指定的附加模块 |
--nocompress |
不压缩initrd映像 |
--builtin 模块 |
指定内置到内核中的模块 |
--fstab 文件 |
使用指定的fstab文件 |
--image-version |
在映像中添加版本信息 |
--verbose |
详细输出模式 |
-v |
显示版本信息 |
-h |
显示帮助信息 |
| 阶段 | 说明 |
|---|---|
| 1. BIOS/UEFI启动 | 系统固件加载引导加载程序(GRUB/LILO) |
| 2. 引导加载程序 | GRUB加载Linux内核和initrd映像到内存 |
| 3. 内核初始化 | 内核解压并挂载initrd作为临时根文件系统 |
| 4. initrd执行 | 运行initrd中的/linuxrc或/init脚本,加载必要驱动 |
| 5. 根文件系统切换 | 挂载真正的根文件系统,切换到真实根目录 |
| 6. 系统初始化 | 执行/sbin/init,启动系统服务 |
# 创建当前内核的initrd映像
mkinitrd /boot/initrd-$(uname -r).img $(uname -r)
# 或明确指定内核版本
mkinitrd /boot/initrd-2.6.32-754.el6.x86_64.img 2.6.32-754.el6.x86_64
# 强制创建,覆盖已存在的映像文件
mkinitrd -f /boot/initrd-$(uname -r).img $(uname -r)
# 预加载SCSI和RAID模块
mkinitrd --preload=sd_mod --preload=ahci /boot/initrd-$(uname -r).img $(uname -r)
# 预加载网络驱动模块
mkinitrd --preload=e1000 --preload=8139too /boot/initrd-$(uname -r).img $(uname -r)
# 省略SCSI和RAID模块(如果没有SCSI/RAID设备)
mkinitrd --omit-scsi-modules --omit-raid-modules /boot/initrd-$(uname -r).img $(uname -r)
# 省略LVM模块(如果不使用LVM)
mkinitrd --omit-lvm-modules /boot/initrd-$(uname -r).img $(uname -r)
# 包含NFS和CIFS模块
mkinitrd --with=nfs --with=cifs /boot/initrd-$(uname -r).img $(uname -r)
# 包含加密模块(dm-crypt, cryptsetup)
mkinitrd --with=dm-crypt --with=cryptsetup /boot/initrd-$(uname -r).img $(uname -r)
# 创建不压缩的initrd(用于调试)
mkinitrd --nocompress /boot/initrd-$(uname -r).img $(uname -r)
# 显示详细的创建过程
mkinitrd --verbose /boot/initrd-$(uname -r).img $(uname -r)
#!/bin/bash
# initrd创建和更新脚本
KERNEL_VERSION=$(uname -r)
INITRD_FILE="/boot/initrd-$KERNEL_VERSION.img"
BACKUP_DIR="/boot/initrd_backup"
DATE=$(date +%Y%m%d_%H%M%S)
echo "当前内核版本: $KERNEL_VERSION"
echo "目标文件: $INITRD_FILE"
# 创建备份目录
mkdir -p $BACKUP_DIR
# 备份现有的initrd(如果存在)
if [ -f $INITRD_FILE ]; then
BACKUP_FILE="$BACKUP_DIR/initrd-$KERNEL_VERSION-$DATE.img"
cp $INITRD_FILE $BACKUP_FILE
echo "已备份现有initrd到: $BACKUP_FILE"
fi
# 创建新的initrd
echo "正在创建新的initrd映像..."
mkinitrd --preload=ahci --preload=ext4 --with=usb-storage --verbose \
$INITRD_FILE $KERNEL_VERSION
if [ $? -eq 0 ]; then
echo "initrd创建成功!"
echo "文件大小: $(du -h $INITRD_FILE | cut -f1)"
# 更新GRUB配置(如果需要)
if [ -f /sbin/grubby ]; then
echo "更新GRUB配置..."
grubby --update-kernel=/boot/vmlinuz-$KERNEL_VERSION \
--initrd=$INITRD_FILE
fi
else
echo "initrd创建失败!"
exit 1
fi
典型的initrd映像包含以下目录结构:
initrd.img (解压后)
├── bin/ # 基本命令(busybox)
├── dev/ # 设备文件
├── etc/ # 配置文件
├── lib/ # 库文件和内核模块
├── proc/ # proc文件系统
├── sys/ # sys文件系统
├── sbin/ # 系统命令
├── init # 初始化脚本(或linuxrc)
└── modules/ # 内核模块
# 创建临时目录
mkdir /tmp/initrd
# 解压initrd(如果是gzip压缩)
cd /tmp/initrd
gzip -dc /boot/initrd-$(uname -r).img | cpio -id
# 如果是xz压缩
xz -dc /boot/initrd-$(uname -r).img | cpio -id
# 查看内容
ls -la /tmp/initrd/
# 安装新硬件驱动后,重新创建initrd
# 1. 安装驱动模块到/lib/modules/$(uname -r)/
# 2. 重新创建initrd包含新模块
mkinitrd --with=新驱动模块 /boot/initrd-$(uname -r).img $(uname -r)
# 创建包含更多工具和驱动的救援initrd
mkinitrd --preload=ahci --preload=sd_mod \
--with=e1000 --with=8139too \
--with=nfs --with=cifs \
/boot/initrd-rescue.img $(uname -r)
# 创建最小化的initrd(仅包含必要模块)
mkinitrd --omit-scsi-modules \
--omit-raid-modules \
--omit-lvm-modules \
--preload=ext4 \
/boot/initrd-minimal.img $(uname -r)
| 工具 | 首次出现 | 特点 | 主要发行版 | 现代替代 |
|---|---|---|---|---|
mkinitrd |
Red Hat 5/6 | 简单、传统 | RHEL 5/6, CentOS 5/6 | dracut |
dracut |
Fedora 12+ | 模块化、灵活 | RHEL 7+, CentOS 7+, Fedora | 当前标准 |
mkinitcpio |
Arch Linux 0.7 | 可定制、hook系统 | Arch Linux, Manjaro | Arch默认 |
update-initramfs |
Debian 4.0 | 自动化、集成 | Debian, Ubuntu | Debian默认 |
如果系统使用mkinitrd但需要迁移到dracut:
# 1. 安装dracut
yum install dracut # RHEL/CentOS
apt-get install dracut # Debian/Ubuntu
# 2. 备份现有initrd
cp /boot/initrd-$(uname -r).img /boot/initrd-$(uname -r).img.backup
# 3. 使用dracut创建initrd
dracut /boot/initrd-$(uname -r).img $(uname -r)
# 4. 验证新initrd
ls -lh /boot/initrd*.img
# 5. 测试启动
# 重启系统并选择新内核
# 错误:No module ahci found for kernel 2.6.32-754.el6.x86_64
# 解决方案:
# 检查模块是否安装
find /lib/modules/$(uname -r) -name "ahci.ko"
# 如果模块不存在,安装相应内核模块包
yum install kernel-modules-extra
# 或手动编译安装模块
# 检查initrd大小
ls -lh /boot/initrd-$(uname -r).img
# 如果过大,创建精简版
mkinitrd --omit-scsi-modules --omit-raid-modules \
--omit-lvm-modules \
/boot/initrd-$(uname -r).img $(uname -r)
# 或者清理旧的内核和initrd
package-cleanup --oldkernels --count=2
# 可能原因:initrd损坏或不兼容
# 解决方案:
# 1. 从救援模式或Live CD启动
# 2. 挂载原系统
mkdir /mnt/sysroot
mount /dev/sda1 /mnt/sysroot
# 3. 重新创建initrd
chroot /mnt/sysroot /bin/bash
mkinitrd /boot/initrd-$(uname -r).img $(uname -r)
exit
reboot
# mkinitrd通常随发行版提供
# RHEL/CentOS 5/6
# 通常已安装,如未安装:
yum install mkinitrd
# 对于更新的系统,可能需要安装传统工具
yum install mkinitrd-legacy
# 从源码编译(不推荐)
# mkinitrd是早期发行版的工具,现代系统建议使用dracut
dracut - 现代initrd创建工具mkinitcpio - Arch Linux的initrd创建工具update-initramfs - Debian/Ubuntu的initrd管理工具depmod - 生成内核模块依赖关系lsinitrd - 查看initrd内容(dracut工具)grubby - 更新GRUB配置uname - 显示系统信息(内核版本)modprobe - 加载内核模块cpio - initrd打包/解包工具