事情起因是我在一台centos上装snapd的时候安装失败,然后发现几乎所有命令都不可用了。除了cd还可以用,ls都用不了了,会报segment fault错误。ssh重新登陆也无法登陆。
当时这台机器就处于这种不可用状态,我很着急,因为这台机器是台共用机器,我也许可以通过重启或者进入拯救模式查找原因,但是不能保证重启能起来或者其他办法能解决问题,那会给别的用户造成很大麻烦。
后来冷静下来想了一下,这个现象很像libc库被误删或者链接错误时的现象。我不知道安装snapd的时候它到底做了什么,也许是对系统库做了什么呢。关于libc库被误删或者链接错误导致系统不可用的情况,算是很常见了,解决方法网上都有,就是执行任何命令之前都用LD_PRELOAD环境变量指定正确的库。
我试了一下
# LD_PRELOAD=/lib64/libc-2.17.so ls
果然不再报segment fault,可以正常执行。
我试图看libc.so.6是否是链接到libc-2.17.so的,
# LD_PRELOAD=/lib64/libc-2.17.so ls -l /lib64/libc.so.6
但是这次报了一个很奇怪的错,跟系统里装的另外一套gcc里的libnss_files.so库有关。
既然看不到链接,我又尝试了一下
# LD_PRELOAD=/lib64/libc.so.6 ls
这次也能正常执行。这说明至少系统的libc库没有被误删,链接也是没有问题的。那问题可能就出在另外一套gcc上。有可能是ld.so.conf设置有问题,导致不能先找到系统的libc库。
所以我接着检查了/etc/ld.so.conf.d/下的内容,果然发现有一个与那个高版本gcc相关的配置文件。
这下就好解决了。以下命令仍然是带着LD_PRELOAD执行的。先把/etc/ld.so.conf.d/xxx.conf删掉,然后清一下ldconfig的缓存文件,就是删掉/etc/ld.so.cache(删除之前可以先备份一份),最后重新执行一下ldconfig刷新一下。
一切恢复正常。命令都可以正常执行,ssh也可以用了。
总结:凡是出现这种什么命令都执行不了的情况,一般都是跟系统底层的libc库有关系。这个时候不要慌,开着的窗口不要退出(退出就再也进不去了),也不要轻易重启,先检查libc库是否正常,如果是正常的,再检查一下ldconfig的路径是否正常。
我这里可能就是安装snapd的时候,它执行了ldconfig,所以xxx.conf里的配置开始生效(之前可能添加了配置文件但没有执行ldconfig,所以系统还都是正常的,但是埋下了隐患),导致系统自带的libc被排到了后面,而它自己的库又有问题,所以导致了系统不可用。
另外,如果安装了别的版本的gcc,最好别轻易修改系统ldconfig路径。可以在想用的时候,直接在命令之前加LD_PRELOAD来运行。万一有问题也不会影响到整个系统。