记glibc升级失败后的恢复

因为云平台上服务器默认的glibc版本较低,一般是2.12或2.14。部分应用要求更高版本的glibc,所以不得不升级。小白一枚,完全不知道从何下手。以为就像其他应用升级,一个yum install就能搞定。问了度娘半天,全是要自己编译安装的…… 没辙,找了一个排版还清晰的贴子就照着干了。

有两个云环境,其中一个上的服务器,从2.12升级2.14,按照教程都顺利升级。另一个按教程升级后,发现连ll命令都报错!,赶紧拿着错误提示去找度娘,折腾了半天,好歹是抢救回来了,可每次进终端都提示本地化配置失败,zh_cn.utf8找不到啥的,但我去本地目录下看了,又有这些文件。想着其他命令能用了就没去管它。


升级glibc2.17

第一次升级。部署某个应用时,提示glibc版本小于2.17。想着折腾过几次,也不是太难。于是参照升级2.14的方法,下载源码编译安装。果然还是跳坑里了,升级失败,拿错误提示去找度娘半天也没能解决。无奈放弃,降回glibc2.14,然后去找了运行在2.14下的旧版应用。

第二次升级。昨天晚上,看到一贴子,可以通过rpm包安装升级glibc到2.17。看起来好简单,两行命令就完成。按耐不住激动的右手,再次去升级。好吧,又跳坑里了,从22点开始折腾,然后升级失败。按上次救火的办法试了居然没效果,看着服务器上120G+没备份的数据,这可咋办呀,这终端断开连接就再也连不上了,顿时睡意全无。还好,折腾到凌晨两点总算是把坑填好了。倒回头来看确实不难,但作为小白的我,完全没有方向……

恩,升级命令是简单,就一行,结果报错了。

root@localhost glibc]# sudo rpm -Uvh *-2.17-55.el6.x86_64.rpm
warning: glibc-2.17-55.el6.x86_64.rpm: Header V3 RSA/SHA1 Signature, key ID 73ec361c: NOKEY
Preparing...                ########################################### [100%]
   1:glibc-common           ########################################### [ 14%]
   2:glibc                  ########################################### [ 29%]
/usr/sbin/glibc_post_upgrade: While trying to execute /usr/sbin/iconvconfig.x86_64 child terminated abnormally
warning: %post(glibc-2.17-55.el6.x86_64) scriptlet failed, exit status 115
error: %pre(glibc-headers-2.17-55.el6.x86_64) scriptlet failed, signal 11
error:   install: %pre scriptlet failed (2), skipping glibc-headers-2.17-55.el6
   3:glibc-devel            ########################################### [ 43%]
error: %post(glibc-devel-2.17-55.el6.x86_64) scriptlet failed, signal 11
   4:glibc-static           ########################################### [ 57%]
   5:glibc-utils            ########################################### [ 71%]
error: %pre(nscd-2.17-55.el6.x86_64) scriptlet failed, signal 11
error:   install: %pre scriptlet failed (2), skipping nscd-2.17-55.el6
error: %triggerpostun(glibc-2.12-1.209.el6_9.2.x86_64) scriptlet failed, signal 11

然后如预期的那样,各种命令报错

rsync: error while loading shared libraries: libc.so.6: cannot open shared object file: Error 40

试着将临时环境变量指向我之前编译过的libc-2.14.so 和libc-2.17.so ,依然不行。上次到这里就恢复正常了呀!心里完全没谱了。

估计是刚才将部分文件升级到2.17版本了,无法直接使用低版本的so库。

反复在这里配置了多次,发现临时环境中加入libc-2.17.so后的错误提供不一样。

export LD_PRELOAD="/opt/glibc-2.17/lib/libc-2.17.so"
ls
ls:relocation error:/lib64/libpthread.so.o:symbol errno,version GLIBC_PRIVATE not defined in file libc.so.6 with link time reference

再去正常的服务器上找,发现glibc编译后,有生成libpthread.so,于是继续指定

export LD_PRELOAD="/opt/glibc-2.17/lib/libpthread.so":$LD_PRELOAD
ls
ls"relocation error: /lib64/librt.so.1: symbol __clock_nanosleep, version GLIBC_PRIVATE not defined in file libc.so.6 with link time reference

提示的so文件又不一样了,继续查询、指定

export LD_PRELOAD="/opt/glibc-2.17/lib/librt.so":$LD_PRELOAD
ls
Segmentation fault

提示是变了,可Segmentation fault?这是什么鬼?网上查了下,说是内存读取错误。这好好的咋就扯上内存了?没提示文件名,这又无从查起。

看了很多帖子,终于在一贴子中看到,博主说在升级glibc主要是对/lib库中的libc.so.6,libm.so.6, libpthread.so.0和librt.so.1这四个文件的修改。看这名字挺眼熟的,这4个文件我已手动指定了3个,难道问题出在剩下那1个文件上?死马当作活马医。

export LD_PRELOAD="/opt/glibc-2.17/lib/libm.so":$LD_PRELOAD
ls
.
..
aaaa
bbbb
...

折腾4小时,终于活过来了。赶紧的修复/lib64 下4个文件的链接,然后备份系统数据。这下总算可以睡的着了。



小结:

glibc是linux的基础运行环境,绝大多数的命令都要依赖glibc,一旦升级出错,将是灾难性的。glibc环境异常,就别想远程连接服务器,只能依靠本地使用引导光盘修复。特别是对于云服务器来说,没有实体机,这glibc环境崩溃,基本服务器就可以格式化重装了。现在想想,真是后怕,当时真是胆大,直接就照着教程开撸。


升级glibc失败后,记得不要断开终端连接,一定不要。断开了就再也连不上了。还好,第一次遇到这情况,终端放一边,赶紧找度娘。虽然ll、rm、mv等命令无法使用,但还是有招的。glibc环境异常实质是链接到libc.so.6等相关文件的目标文件异常,我们只要能把它修复成正确的链接就能解决问题。有几个命令不依赖glibc环境,可以用于救急。

一是sln命令,用于创建文件链接,我在使用中有时会遇到提示“链接层数过多”的错误。

二是export命令,用于指定临时使用的环境变量。使用export LD_PRELOAD="/opt/glibc-2.14/lib/libc-2.14.so"  只要指定了正确的so文件(这里需要指向你编译的或者是备份的so文件),所有的命令就可以使用了。这只是针对当前连接,趁现在应该去修复/lib64/libc.so.6的链接,否则就哭吧。

三是直接使用LD_PRELOAD。

# LD_PRELOAD=<real libc> ln ......


相当于直接调用 ln命令,
所以,
先删除连接 :

# cd /lib
# LD_PRELOAD=/opt/glibc-2.14/lib/libc-2.14.so rm libc.so.6


再建立新连接 :

# LD_PRELOAD=/opt/glibc-2.14/lib/libc-2.14.so ln -s /opt/glibc-2.14/lib/libc-2.14.so libc.so.6


原理就是: 

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


评论

    Error (#32) - KOKO.VC

    Error (#32)

    An internal server error occurred.

    The above error occurred while the Web server was processing your request.

    Please contact us if you think this is a server error. Thank you.