一、故障现象

现网一台redhat6主机自从被业务人员升级编译过某软件包以后,ssh无法正常登陆,登陆报错为libc.so.6: cannot open shared object file ,ldd 查看确认,使用的libc.so.6文件位于/lib64目录下。

1[root@361way ~]# ldd /usr/sbin/sshd |grep libc.so
2        libc.so.6 => /lib64/libc.so.6 (0x00007fa2017ed000)

通过查看该文件发现是一个软链接文件:

1[root@361way ~]# ll /lib64/libc.so.6
2lrwxrwxrwx 1 root root 12 Jul 15 21:50 /lib64/libc.so.6 -> libc-2.14.so

二、故障解决

通过对比同版本正常主机另一台redhat6主机,发现使用的libc.s0.6软链接的是libc-2.12.so 文件 ,所以可以确认该包被业务人员源码编译的时候升级了。按照之前的经验,将当前的软链先备份后再删除,然后重新链接 libc-2.12.so 文件即可解决问题。不过在执行rm -rf /lib64/libc.so.6后,再执行ls、mv、ln、cp等任一命令时都会出现类型如下的报错:/bin/ls: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory

网上查找该报错后,发现可以通过使用LD_PRELOAD解决,方法如下:

先删除连接 :

1# cd /lib64
2# LD_PRELOAD=/lib64/libc-2.3.6.so.bak rm libc.so.6  -->我可以正常删除,这一步省略,不能正常删除的,先执行该步
3建立新连接 :
4# LD_PRELOAD=/lib64/libc-2.3.6.so.bak ln -s /lib64/libc-2.3.6.so.bak libc.so.6

注:从redhat7以后已经没有x86位系统,老的x86位系统lib文件位于/lib目录。另外需要注意的是LD_PRELOAD与后面跟的命令rm 、ln等必须在同一行,不可以先执行LD_PRELOAD后再执行ln -s ,这样还是会报错。

三、原理分析

LD_PRELOAD解决的原理是:linux调用so的库文件时,搜素路径为当前路径,再是系统lib目录。但是提供了一个LD_PRELOAD系统变量来改变这个顺序。设置LD_PRELOAD了后,库加载的顺序就改为:

搜素路径为: LD_PRELOAD ,当前路径,再是系统lib目录

当然,解决方法并非这一种,还可以使用网上推荐的另外一种方法busybox法,在redhat6版本上的busybox不依赖任何lib库文件的,如下:

1[root@361way ~]# whereis busybox
2busybox: /sbin/busybox /usr/share/man/man1/busybox.1.gz
3[root@361way ~]# ldd /sbin/busybox
4        not a dynamic executable

注意,这里并非绝对,一些发行版本上busybox是会依赖如libc.so.6库文件的。

通过busybox ln 或busybox rm 等执行想要的操作。

总结:这里的出错只能算是一个小问题,如果出现shell 都无法执行时,就需要修复模式或光盘引导进行解决了,如果缺了相应的包文件,还在在修复查模式下,安装相应的软件包 --- 具体可以参看之前的博文redhat修复模式安装丢失的包及grub引导修复