现象
某次更新尝试后重启服务器报错:
VFS: Unable to mount root fs on unknown-block(0,0)
原因
在我所在的区域,直接访问我的海外vps十分不便,因此采用跳板机的方式通过国内的vps进行访问。
在我这次定期更新所有服务器的过程中,由于连接国内跳板机的服务器速度较快,而连接国外vps的速度较慢,因此在更新完成国内跳板机后国外vps仍处于升级的过程中,然后由于我短暂忘记了跳板的关系,直接输入reboot重启了国内跳板机来应用更新。此时连接中断,国外vps的更新过程未完成。且由于使用的terminal有断线重连的功能,当我再次检查到这台国外vps后它已经显示了可交互的shell,我没有细看上方报错情况便误认为更新已完成于是进行了重启。但是实际上此时的过程非常巧妙地位于更新完成了新的内核,但对应的initramfs没有生成的情况,导致无法挂载根目录,最后只能报错。
排查过程
只看排查出来的结果很难学到什么新东西,因此我记录下来自己的排查思路以供参考。
服务器状态排查
更新并重启后发现无论等多久都无法成功连接,而跳板机却能连接成功,因此尝试排查目标海外服务器状态。
使用的服务商提供vnc连接,在连接后可直接查看虚拟显示器。发现报错
VFS: Unable to mount root fs on unknown-block(0,0)
因此确定是启动内核并在挂载rootfs时失败。
排查/boot目录
云服务商有救援模式会在对应机器临时开起来一个live系统,我可以通过它挂载磁盘来进行检查。
在将根目录分区挂载到/mnt目录后查看/mnt/boot目录,发现新安装的内核5.14.0-687.38.1.el9_8.x86_64对应的initramfs——/boot/initramfs-5.14.0-687.38.1.el9_8.x86_64.img没有正常生成,而旧版本内核都存在对应的initramfs。判断为在更新内核的重新生成initramfs阶段被中断,毕竟之前的观察来看这个阶段的运行耗时较长。
选定旧内核启动
因此问题很明显了,即安装新内核后对应的initramfs更新失败,且此时指定了新的内核作为首选,导致无法正常挂载rootfs。因此选择旧的内核启动。
先挂载虚拟文件系统:
1 | |
再chroot:
1 | |
另外,此时执行
1 | |
其实应该可以看到默认启动的内核为/boot/vmlinuz-5.14.0-687.38.1.el9_8.x86_64。
接下来执行以下代码来修改默认启动的内核为旧的5.14.0-687.26.1.el9_8.x86_64内核:
1 | |
虽然理论上通过vnc直接在grub界面直接选择内核更简单,但是我使用的云服务商在重启机器后不会重新连接vnc,重连耗费时间较长很容易错过这个,因此还是指令设置可靠一些。
然后重启机器,不出意外应该能正常启动。然后重新安装新kernel相关包:
1 | |
或者此时由于只是initramfs没有成功创建,可以直接执行
1 | |
来重新给已安装的内核生成initramfs。
但是由于我不确定是否还有别的内核相关包的脚本未被执行,modules相关的包大概也没有重新安装的必要,总之我是全重装了。
接下来重新指定新内核为默认的启动内核
1 | |
重启,可正常进入系统。