JUN

重构 initramfs 正确引导内核启动
本来有一台专门用来编译的服务器一直用着 4.9 版本的内核,闲着没事就想升级到 4.15 系列跟进大流。然后悲剧就...
扫描右侧二维码阅读全文
24
2018/02

重构 initramfs 正确引导内核启动

本来有一台专门用来编译的服务器一直用着 4.9 版本的内核,闲着没事就想升级到 4.15 系列跟进大流。
然后悲剧就发生了。
内核没有自己编译,安装用的是 elREPO 源(http://elrepo.org/tiki/tiki-index.php

# yum --enablerepo=elrepo-kernel install kernel-ml

装完之后看了看 /boot/grub2/grub.cfg 最新装上的内核排在第一个,设置了一下引导顺序就直接重启了

# cat /boot/grub2/grub.cfg | grep menu
# grub2-set-default 0
# systemctl reboot

之后等了很久就是没法连上 SSH,进IDRAC界面看了下,发现系统引导卡在这个地方

... ...
[ 189.478627] dracut - initqueue[312]:Warning: dracut-initqueue timeout - starting timeout scripts
[ 189.479027] dracut - initqueue[312]:Warning: Could not boot.
[ 189.922409] dracut - initqueue[312]:Warning: /dev/disks/5058256d-xxxx-xxxx-xxxx-45b98cfe68fe does not exist.

Starting Dracut Emergency Shell...

Entering Emergency mode. Exit the shell to continue.
Type "journalctl" to view system logs.
You might want to save "/run/initramfs/rdsosreport.txt" to a USB stick or /boot
after mounting them and attach it to a bug report.

dracut:/#

看样子是没有找到引导盘。
哦?难道安装个新内核,连个设备的 UUID 都会变的?
甚至在 dracut 救援模式下 ls /dev/disk 目录都没有被列出来。

Linux 系统的引导过程

要排除这个问题,先了解一下 Linux 系统的引导过程。
在 BIOS 自检完之后,会通过 INT 13H 中断读取硬盘第0道第0磁头第0扇区(MBR, 主引导记录)。
这个扇区一般是 512Bytes 大小,其中 64Bytes 存放分区表数据,剩下 446Bytes 是 bootloader,用来引导内核。(还有 2Bytes 是拿来记录这块设备是否可以用来引导)
待 BIOS 找到 bootloader 之后就把控制权交给 bootloader,至此 BIOS 完成自己的任务,功德圆满。
bootloader 的任务就是载入操作系统内核,如有必要还会预先加载一个虚拟的文件系统(initramfs, 本文的主角),来使内核完成对各种模块的加载。
据我的了解,grub2 是认得文件系统的,因为它要加载 /boot/grub2/grub.cfg 配置文件,这个只有 446 字节的程序有点厉害啊。
但是内核并不认得文件系统,但是又必须从文件系统(一般是 /lib/modules 目录下)加载模块支持,这时候就需要 initramfs 的登场了。

问题排除思路

首先从救援模式启动,按以下步骤将引导盘“挂载”为根目录。其中,sda1/bootsda2/

# mount /dev/sda2 /mnt
# mount /dev/sda1 /mnt/boot
# mount --bind /sys /mnt/sys
# mount --bind /proc /mnt/proc
# mount --bind /dev /mnt/dev
# chroot /mnt

然后看看 /etc/fstab

# cat /etc/fstab
UUID=5058256d-xxxx-xxxx-xxxx-45b98cfe68fe /                       ext4    defaults        1 1
UUID=8e1fb56c-xxxx-xxxx-xxxx-975a485cb3c7 /boot                   ext4    defaults        1 2
UUID=049616f4-xxxx-xxxx-xxxx-ea82b6526fd1 swap                    swap    defaults        0 0

奇怪了,明明就有啊,为什么引导的时候找不到呢?
那一定是 initramfs 在给内核加载模块的时候找不到 SATA 驱动,没有把硬盘带起来,所以超时报错了。

知道问题所在,就好着手解决了。我们只要重构 initramfs,给它加上硬盘驱动就好了。
dracut 命令正是拿来构建 initramfs的。它的格式是

racut [OPTION...] [<image> [<kernel version>]]

具体可以man dracut看一下。需要补充的是,如果你需要指定内核版本,请按着 /lib/modules 目录下存在的版本来。

# cp initramfs-4.15.4-1.el7.elrepo.x86_64.img initramfs-4.15.4-1.el7.elrepo.x86_64.img.bak
# dracut -f initramfs-4.15.4-1.el7.elrepo.x86_64.img 4.15.4-1.el7.elrepo.x86_64
# exit
# systemctl reboot

重启之后 IDRAC 界面里已经出现可爱的登录画面了~
idrac.jpg

后记

之前不了解 bootloader 的启动过程,只知道有这么个东西为我们加载了内核。
前后足足花了两天时间研究。查了不少网站才终于悟出解决之道。
其实这台服务器只拿来编译东西,完全可以通过服务器后台重装系统,再重新安装编译环境。
但每次 Trouble shooting 都是一次成长。
请珍惜每一次遇到问题的机会吧!

感谢这些网站给了我解决问题的思路。
https://www.centos.org/forums/viewtopic.php?t=56591
https://forums.fedoraforum.org/showthread.php?288020-Cloning-boot-and-root-partitions-F18-dracut-issue
https://forums.fedoraforum.org/showthread.php?292910-Help-with-a-boot-error-dracut
https://stackoverflow.com/questions/37904955/warning-could-not-boot-warning-dev-disk-by-uuid-xxxx-does-not-exist-start

Last modification:February 25th, 2018 at 01:56 am
If you think my article is useful to you, please feel free to appreciate

2 comments

  1. 青衣

    晕,你这个网站名称有点吓人。看到还以为谁走了……

    1. JUN
      @青衣

      啊哈哈 欢迎来看

Leave a Comment