问题描述

公司一同事在做主机配置时,不小心在根目录下执行了mv * /bak/的操作,后来ctrl + c 停止后,发现所有的命令都已无法操作了,所幸当前连接的ssh还没断掉,但新发起的ssh明显也连不过去了。执行任何命令都发现无法操作。通过全路径执行也主要报错:“/lib64/ld-linux-x86-64.so.2: bad ELF interpreter: No such file or directory”

解决过程

首先想到的是可以通过管理口重启主机,光盘引导进入修复模式,这个是最简单的,进入单用户后,把文件mv回去就OK了。不过由于机器在异地云机房,不便于管理口操作。机房如果操作,一般只提供重装,不提供修复。所以该思路先否决了;

既然这个行不通,就想到了个瑞士军刀级工具busybox,该工具包含了n多个命令,且无需动态链接库依赖,直接可以使用,如下:

1[root@201 tmp]# ldd /tmp/busybox
2        not a dynamic executable
3[root@201 tmp]# /tmp/busybox pwd
4/tmp

不过测试了几个指令都无法进行网络下载— 像wget curl 之类的全部需要动态so文件依赖,发现通过其他主机和该主机进行网络交互行不通。该步骤也只能放弃了。

接下来想到,如果指令所需的连接库文件找不到,是可以把连接库的全路径加在命令前去执行的,比如ls命令执行时报错找不到ld-linux.so文件,就可以按下图执行:

ld-linux
ld-linux

可以看到我将/lib64/ld-linux-x86-64.so.2加在前面后,又报缺失libselinux.so.1,当然我们还可以把这两个so文件的路径一起加在前面用,一起加在前面后,又报错“libpcre.so.1: cannot open shared object file”,这是一个无休止的循环啊,当我们把有连接库文件全加上,再执行的时候,报错:libselinux.so.1[28927]: segfault at b ip 000000000000000b sp 00007fff24cc7198 error 14 in libselinux.so.1[7fa3722ac000+21000]

想了下,能解决该问题,可能有效几的命令可能有cp mv rsync scp cat ln wget curl 几个,在执行到ln指令的时候,神奇的事情发生了,ln可以成功调用,其所依赖的库确实比较少(具体可以ldd指令查看),所以先执行如下操作,把lib64给连接回去:

1/bak/lib64/ld-linux-x86-64.so.2 /bak/bin/ln -s /bak/lib64 /lib64

lib库问题解决后,后面就好搞定了,用全路径运行指令即可,如下一段命令所有问题都可以还原了:

 1/bak/bin/cp -rp /bak/usr/* /usr/
 2/bak/bin/ln -s /usr/bin /bin
 3/bak/bin/ln -s /usr/sbin /sbin
 4/bak/bin/ln -s /usr/lib /lib
 5alias cp='cp'
 6cp -rp /bak/lib/* /usr/lib/
 7cp -rp /bak/var/* /var/
 8cp -rp /bak/lib64/ /lib64_bak
 9rm -rf /lib64
10/lib64_bak/ld-linux-x86-64.so.2 /usr/bin/ln -s /usr/lib64/ /lib64
11tar czvf lib64.tar.gz /lib64_bak
12rm -rf /lib64_bak
13ln -s /usr/lib /lib

总结

该问题当时的解决有一点的侥幸性,因为其在mv还没有执行完的时候,提前中断了操作。后面在搭建的测试环境中测试在让mv完全把lib64 lib sbin bin usr几个目录移走之后,使用ln调用时,在使用完ld-linux-x86-64.so.2后,还报有libc.so.6文件依赖,这两个都调用后,执行ln虽然没有明确再报缺少文件,不过执行完后,直接跳了一个cc编译器的bug报错界面。如下:

libc-so-error
libc-so-error

所以这里猜测,其在mv的过程中,可能lib64并没有移走完,像libc.so.6文件可能还在原来的地方。不过遇到这种情况是真没办法解决了吗?实际上还是有的,在查看ld-linux.so的帮助信息时,查到可以使用如下方法解决:

1/bak/lib64/ld-linux-x86-64.so.2  --library-path /bak/lib64/ /bak/bin/ln -s /bak/lib64 /lib64
23export LD_LIBRARY_PATH=/bak/lib64
4/bak/lib64/ld-linux-x86-64.so.2 /bak/lib64/ /bak/bin/ln -s /bak/lib64 /lib64

其实通过指定library-path的方式,不但ln指令可以直接用,其他任一指令都可以直接用。当然这里是你知道别人做了什么的前提下,所以在不知道别人做了什么的情况下,最好可以备一个busybox程序到/root下去,文件比较下几有几百k,功能却比较强大,可以在出现这种情况下,临时就用上了。