Linux服务器升级GLIBC失败导致shell命令不可用怎么解决
在某些linux系统里面本身自带的glibc版本过低,导致rpm无法安装。如果你直接更新系统的glibc版本会导致系统崩溃,就算你编译安装好glibc库到非系统目录,但是你不能去设置环境变量 和ld.so.conf 这个2个文件,你一但设置指向新版本的glibc库,系统分分钟崩溃。更不能把这个新库直接安装到系统目录下。笔者最近不幸遇到了这个问题。
glibc介绍
glibc是什么?为什么升级风险这么高?glibc的作用是什么?
glibc是GNU发布的libc库,即c运行库。glibc是linux系统中最底层的api,几乎其它任何运行库都会依赖于glibc。glibc除了封装linux操作系统所提供的系统服务外,它本身也提供了许多其它一些必要功能服务的实现。内核实现一个功能,glibc要花很久才会用上,由于glibc和内核不是一块开发的,所以glibc需要去兼容不同版本的内核,而内核也要去兼容不同版本的 glibc,双方都背负了太多的历史包袱。
简单理解其实和http api接口类似,区别在于glibc是调用内核对底层磁盘,内存,网卡等的操作,http api则是对应用层app的操作,比如听一首歌,下载一部电影实则都是在调用http api接口。
问题发生
试图通过编译安装升级Linux服务器的glibc库版本,install失败以后,shell中的大部分命令(ls,cat,rm,cp,ln,scp,vi,yum等)都执行报错,尝试新的ssh连接时提示拒绝连接。
命令报错类似:
或者
可补救·操作空间
有ssh客户端连接着这台服务器没有断开原始的低版本glibc库文件还在cd,pwd,export,echo,sln,chmod命令可用,输入ls+两次TAB键可以提示目录下所有文件
开始尝试修复
步骤1
glibc是Linux系统底层库,许多shell命令乃至bash本身都依赖这套动态链接库。
以上问题出在/lib64(/usr/lib64)
目录下的软连接损坏,或连接的so库文件版本不统一,或所连接的so库文件本身存在问题。
解决思路就是把以下软连接全部恢复为指向原始版本(低版本)。
前提是先到/lib64
目录下,用ls+两次TAB键的方法确认好自己系统下的libc-<x.xx>.so
最低版本号(也就是好用的版本)是哪个。
步骤2
由于ln命令已经不能使用,可使用sln命令,创建/修复软连接。命令格式:sln <被指向的文件> <软连接名>
。假设需要回退到版本号XXX,那么只需以下命令就可以修复。
至此,如果没有操作错误,ls等关键命令、包括ssh连接都应该已经可以正常使用,修复完成。
但是,由于笔者操作过程中的失误(“sln xxx yyy"写成了"sln yyy xxx”),导致ld-2.17.so原始库文件被覆盖成软连接文件,所以需要进一步的补救。
误操作后的二次补救
解决思路就是恢复不小心损坏的ld-2.17.so文件,那么就需要一份可用的ld-2.17.so文件数据。由于笔者使用的是服务器集群,原始文件从其他节点就可以获取。如果是单机服务器,可能需要借助互联网获取ld-2.17.so原始文件。
目前最大的阻碍是:scp,mount,wget等命令都不能使用,需要考虑如何将获取到的原始文件放到问题服务器的磁盘上——解决方法是echo命令+重定向输出文件,具体展开如下:
以文本编辑器(例如使用Windows上的EmEditor)的二进制模式打开原始文件,全选复制出文件的原始字节内容,如下:
继续编辑文本,替换复制内容中的" “(1个空格)和” “(2个空格)替换为”\x",并且在每行首也插入"\x",如下:
合并所有行为一行,并去掉所有空格,如下:
将编辑后的十六进制数据与echo命令参数一起,组成echo -e "编辑后的16进制数据" > ~/savetheworld.bin
的形式,粘贴到连接着问题服务器的ssh终端,执行。经过漫长的等待之后(以小时记,因为回显很慢。可灵活利用shell客户端中类似CommandWindow的功能,在输入框中输入命令来节省时间),生成的~/savetheworld.bin
文件就作为损坏的ld-2.17.so文件的替代,重新用上文sln修复软连接的方法,最终修复成功。
总结
你只能用第三方工具把glibc引入你的项目,第一是让rpm安装包自带这个库 ,第二种是 使用yum或者其他第三方工具库进行安装 ,第三种就是换更新的系统 ,新出的系统里面自带高版本glibc。我建议直接换系统 如果对系统版本没有强制要求的情况。