前言
上周帮用户处理了一个 linux 虚拟机在重启后无法正常进入操作系统的故障,觉得比较有意思,在这里分享给大家。
1. 故障描述
事情的起因是一台系统版本为 CentOS 7.2 的 VMware 虚拟机出现了 ssh 登录报错,然后客户就想着通过重启操作系统的方式看看能否解决问题,结果发现重启后操作系统直接就起不来了,卡在如下所示界面:
故障表现即:不管怎么重启虚拟机,最后都会卡在 Starting Switch Root...
这里,在等待较长时间后会提示 Failed to execute /bin/sh, giving up: No such file or directory
。
2. 故障诊断
Step1
:在接到客户的消息时,我脑海里第一时间想到了如下几种可能性:
- 系统 Crash 了?
- 系统
/etc/fstab
文件中某些设置了开机自动挂载的项挂载失败了? - 磁盘或者分区出现了坏块?
Step2
:联系客户发起远程,由于客户也不清楚系统在发生故障前都做了哪些操作,所以想着还是先进单用户模式做个初步排查,结果在执行 chroot /sysroot
时出现了如下报错:
到这一步时我开始觉得这个故障的原因和我一开始想象的不一样了,因为之前处理过的一些故障,还从来没有遇到过进单用户模式在切换根环境变量时出现报错。
Step3
:既然单用户模式在切换根环境变量时报错,我想着那进救援模式是不是也会报错呢?接下来就让用户挂载了一个 CentOS 7 版本的镜像进救援模式,果然不出所料,在执行 chroot /mnt/sysimage
切换根环境变量时也出现了如下报错:
Step4
:接下来就是要检查 /bin/sh
和 /bin/bash
两个文件是否存在,查询完发现系统提示没有该文件:
特别说明:这里有个点需要注意下,因为不管是单用户模式还是救援模式,我们其实都没有成功切换到系统的根环境变量下来,所以在查询时一定要注意你查看的是 iso 救援模式系统的信息还是故障主机的系统信息
。如上图所示,编号为1的地方我们查看的信息就是 iso 救援模式系统的,而编号为2的地方查看的才是故障主机系统的信息,由此可以判断,原系统里面就是缺少了 /bin/sh
和 /bin/bash
两个文件。
Step5
:带着关键报错信息和疑问去网上查了一些资料,类似的故障案例里面有说是因为 /lib64
的软链接异常导致的,后面看到了红帽官网的《Kernel panicked on boot and ‘chroot /mnt/sysimage’ command in rescue mode fails with ‘chroot failed to run command /bin/sh no such file or directory’ error》 这篇 KB 文章。
1)首先我查看了下 /lib64
的软链接信息,发现软链接是正常的(此时我以为是正常的,其实被误导了,后面会说):
sh-4.2# ls -l /mnt/sysimage
2)紧接着我又查看了下 /bin
目录的信息(此时我还以为是正常的,呵呵):
3)接着我按照红帽官方 KB 所提供的步骤去做检查:
敲重点:终于在这一步我发现了问题,因为前面的检查让我认为不管是 /lib64
的软链接还是 /bin
的软链接都是正常的,但是当我在执行 /mnt/sysimage/lib64/ld-linux-x86-64.so.2
命令时发现 ld-linux-x86-64.so.2
居然不能自动补全,此时我开始怀疑:虽然软链接看似存在,但是源文件 /usr/lib64
可能缺少了;再联想到 /bin
目录也从 /usr/bin
软链接过来的,但前面查询时明明提示 /bin/sh
和 /bin/bash
两个文件也是不存在的;基于此,我愈发觉得可能是 /usr
目录有异常。
Step6
:检查发现原系统的 /usr
目录下除了一个 local 目录,其余啥也没有,此时终于找到“罪魁祸首”了,就是因为 /usr
目录下的其它文件被删除了,所以即使 /lib64
的软链接和 /bin
的软链接看着都正常,但其实已经失效了。
故障原因已经定位到,接下来就是该如何解决问题了。
3. 故障原因
系统 /usr
目录下的文件被删除,导致很多从 /usr
目录下的文件创建的软链接失效,如 /usr/lib64
和 /usr/bin
等,从而出现 ssh 登录报错,甚至重启后无法进入操作系统。
系统 ssh 服务依赖的关键文件主要位于 /usr/sbin/sshd 和 /usr/lib64
,因此系统 /usr
目录下的文件被删除,ssh 肯定会受到影响;其次,登录系统所需的 bashshell 通常位于 /usr/bin/bash
,这也是为什么系统在重启后会卡在 Starting Switch Root...
这里进不去,而在单用户以及救援模式下我们也无法切换到根环境变量下。
除此之外,用户环境配置所需的很多工具如 ls、grep 等命令都在 /usr/bin
下,所以当 /usr
目录下的文件被删除,在使用这些命令时肯定也会报错的(后面我自己复现了故障并进行了验证)。
4. 解决方案
由于客户没有做任何的备份,也没有虚拟机快照,因此只能通过挂载一个和故障主机操作系统版本一致的 iso 镜像,进入救援模式后采用 cp -a
命令,将 iso 救援模式系统里原生的 /usr
目录下的所有文件全部拷贝到 /mnt/sysimage/usr
目录下去。
通过上图不难发现,在拷贝操作完成后,此时可以成功执行 chroot /mnt/sysimage
切换到根环境变量。
后面取消 iso 挂载,重启虚拟机就正常进入系统了。不过值得注意的是,此举只能保证系统可以正常进入,但是如果之前有一些应用程序安装在 /usr 目录下,那么很大可能应用程序会无法正常被执行;又或者用户自己的数据保存在 /usr 目录下,此时也是没有办法恢复的。
总结
虽然这次故障基本上得到了解决,但是也反映出我自己对 linux 文件结构还是不够熟悉,否则在看到 ssh 登录异常、/bin/sh
异常以及 /bin/bash
异常时,就应该第一时间想到去查看 /usr
目录的。
另外,日常工作中还是要建议客户加强备份建设,这样一旦出现故障,保底还有备份集可以进行还原;除此之外,在虚拟化环境中如果要对虚拟机做一些风险不可控的操作,建议先打快照再操作,这样即使出现了问题,恢复快照就可以了。