为了安装promtail日志采集工具,提示我需要升级glibc到2.34版本。也许是对于这次升级的自信,因为之前也升级过,并无问题。没想到系统的不同升级glibc带来的影响也不同。而且这次升级编译安装时候并未指定单独的prefix目录。导致 make install
后出了问题,几乎所有的系统命令无法使用。如 rm、ls、mv 等均提示 Segmentation fault (core dumped)
,也无法再次ssh登录设备。没错出问题的正式我的博客服务器。身为一名运维,得有一个临危不乱的心态。下面就说说我解决这个问题的方式。
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接口。
问题复现
[root@blog ~]# wegt https://mirror.fcix.net/gnu/glibc/glibc-2.34.tar.gz
[root@blog ~]# tar -xf glibc-2.34.tar.gz && cd glibc-2.34
[root@blog glibc-2.34]# mkdir build install
[root@blog build]# cd build
[root@blog build]# ../glibc-2.34/configure --prefix=/usr
[root@blog build]# make
[root@blog build]# make install
# make install DESTDIR=/xxx/xxx/install 在install时候使用DESDIR指定安装目录会覆盖configure时候prefix指定的安装目录。
到此安装完以后系统命令就开始无法使用了,但是正在运行中的进程是正常的。因为正在运行的进程在启动时候就以将glibc加载到内存使用,也就是老版本正常的glibc。但是当我们执行ls命令等,则是刚运行的将会调用最新的glibc 就无法正常执行。报错如下:
[root@blog lib64]# ls
Segmentation fault (core dumped)
解决思路
抢救要求
此时就算如上报错,业务任然是正常的。所以千万慌张,还不能瞎动。如果不想影响业务,务必做到以下两点:
- 不要重启服务器,重启不光影响业务。服务器启动时候也是启动不起来的。
不要断开此时的ssh连接,因为这时候这个连接已是唯一还能操作这台服务器的。
如果不满足以上两点,那不好意思业务得断了。必须进入系统安全模式处理。安全模式下处理我就不介绍了。
实施抢救
问题出在新版本的glibc,那就想办法将版本回退。这里我推荐大家使用finalshell,也正是FinalShell拯救了我!从FinalShell中我们依然可以查到,libc的历史版本是2.28。每个操作系统情况可能不一样,建议查看文件修改时间,看下其他库文件是否也更新了。(图中是我已回退的库文件)
<img src="https://storage.bbcking5.com/文章内部图/自动/image-20240715215206368.png" alt="image-20240715215206368" style="zoom:50%;" />
[root@blog lib64]# ldconfig -lv /usr/lib64/libc-2.28.so
ldconfig: /usr/lib64/libc.so.6 is not a symbolic link
# 尝试手动重新链接旧的库文件,结果报错,很明显新版本的 libc.so.6 文件占坑了。那就把它删了。
[root@blog lib64]# rm -f libc.so.6
Segmentation fault (core dumped)
[root@blog lib64]# rm -rf libc.so.6
Segmentation fault (core dumped)
[root@blog lib64]# mv libc.so.6 /opt/
Segmentation fault (core dumped)
# 一通操作也无法将其删除,最后还得靠FinalShell,我尝试在如上图中右键删除,还真给删除了。
[root@blog lib64]# ldconfig -lv /usr/lib64/libc-2.28.so
libc.so.6 -> libc-2.28.so (changed)
# 当再次尝试手动重新链接旧的库文件,已正常链接。其他命令也都恢复了正常、ssh也能正常登录,危机解除。
术后小结
- 生产环境glibc不要随便乱升。
- 就算要升级,编译前configure请指定一个自定义目录,不要用系统目录。或者install时候务必指定一个自定义目录。再去
/etc/ld.so.conf.d/
目录中手动配置库文件进行加载,这样就算有问题也好处理,删除配置重启系统就能解决。 - 推荐使用FinalShell,真心不错。缺点就是java开发的,有点吃内存。
本文由mdnice多平台发布
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。