glibc 版本异常

事情起因

发现有一台物理机只能连接同一个网段的公网,不能访问如百度,dns服务器也ping不通,我就想装个traceroute 看看是哪一步的原因,由于这台机器不能联网,于是就打算从隔壁机器下载deb包,到这个机器上安装。于是:

# 获取依赖,并下载
apt-rdepends traceroute | grep -v "^ " | xargs sudo apt-get download
# 打包
tar zcvf traceroute.tgz traceroute/
# 远程复制
scp <>
# 解压
tar zxvf traceroute.tgz 
# 安装
cd traceroute&&dpkg -i *.deb

一气呵成,问题来了,所有命令都用不了了,报错/lib/x86_64-linux-gnu/libc.so.6: version 'GLIBC_2.30' not found (required by /lib/x86_64-linux-gnu/libselinux.so.1)
后来发现,隔壁机器跟这个机器不是同一个版本的操作系统,而且这些安装包里包含:gcc-6-base_6.0.1-0ubuntu1_amd64.deb libc6_2.23-0ubuntu11.3_amd64.deb libgcc1_1%3a6.0.1-0ubuntu1_amd64.deb traceroute_1%3a2.0.21-1_amd64.deb。好好好。只能怨我眼瞎。犯了这么低级的错误。
更离谱的来了,因为我是刚来这家公司,发现这个k8s集群的部分woker节点情况如下:

   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIME
   Ubuntu 18.04.1 LTS   4.15.0-147-generic   docker://19.3.13
   Ubuntu 16.04.3 LTS   4.4.0-210-generic    docker://19.3.13
   Ubuntu 16.04.2 LTS   4.4.0-210-generic    docker://19.3.13
   Ubuntu 16.04.3 LTS   4.4.0-210-generic    docker://17.9.0
   Ubuntu 16.04.3 LTS   4.4.0-210-generic    docker://19.3.13
   Ubuntu 16.04.2 LTS   4.4.0-210-generic    docker://18.6.0
   Ubuntu 16.04.2 LTS   4.4.0-62-generic     docker://19.3.13
   Ubuntu 16.04.2 LTS   4.4.0-62-generic     docker://18.6.0
   Ubuntu 16.04.3 LTS   4.4.0-91-generic     docker://19.3.13
   Ubuntu 18.04.4 LTS   4.15.0-192-generic   docker://19.3.11
   Ubuntu 18.04.4 LTS   4.15.0-156-generic   docker://19.3.12
   Ubuntu 20.04.5 LTS   5.4.0-125-generic    containerd://1.6.12
   Ubuntu 20.10         5.8.0-63-generic     docker://20.10.6
   Ubuntu 20.04.5 LTS   5.4.0-125-generic    docker://20.10.18

好巧不巧,我操作的就是这个 ubuntu 20.10。这个版本从发布到中止维护仅有9个月的时间。都是前人挖的坑啊。
此情此景,我只能说 k8s 牛逼,不挑食。
言归正传。现在什么命令都用不了。

自救过程

现在已经打开的ssh是没有断开的,但是新的ssh已经连接不了了。根据网上的方法:
上传20.10用的glibc版本的 libc-2.32.so

LD_PRELOAD=/home/sysuser/libc-2.32.so  ls

然而,并没有什么用。于此同时,我还手贱的打算复制一个ssh连接,好家伙,windterm直接闪退。
那没有办法了,就只能去机房操作了。

首先了解一下这次操作到底都更新了哪些文件

这里使用docker的 layer 机制,就能很明显的看到那些文件发生了改变

# 运行一个ubuntu 20.10的容器
docker run -it --name ubunt-2010 -v /root:/data ubuntu:20.10 bash
# 安装相关的包
cd /data/traceroute
dpkg -i *.deb
# 发现问题与线上问题一致
root@ubuntu-2010:/data/traceroute# ls
ls: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28' not found (required by ls)
ls: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.30' not found (required by /lib/x86_64-linux-gnu/libselinux.so.1)
root@ubuntu-2010:/data/traceroute# cp
cp: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.25' not found (required by cp)
cp: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28' not found (required by cp)
cp: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.30' not found (required by /lib/x86_64-linux-gnu/libselinux.so.1)

接下来另起一个窗口:

docker inspect ubuntu-2010 --format '{{.GraphDriver.Data.UpperDir}}'
# cd 到这个目录
cd <上一步输出结果>
# 查看哪些文件夹发生了改变
tree
# 这里发现很多文件都改变了,于是只看看哪些目录
tree -d
.
├── data
├── etc
│   └── ld.so.conf.d
├── usr
│   ├── lib
│   │   ├── gcc
│   │   │   └── x86_64-linux-gnu
│   │   │       ├── 6
│   │   │       └── 6.0.0 -> 6
│   │   └── x86_64-linux-gnu
│   │       ├── audit
│   │       └── gconv
│   ├── lib64
│   └── share
│       ├── doc
│       │   ├── gcc-6-base
│       │   └── libc6
│       └── lintian
│           └── overrides
└── var
    ├── cache
    │   └── debconf
    ├── lib
    │   └── dpkg
    │       ├── info
    │       ├── triggers
    │       └── updates
    └── log

在启动一个新的ubuntu 20.10的容器,对比发现 /usr/lib/gcc/x86_64-linux-gnu目录是新增的,新增一般影响不大。主要变动就是/usr/lib/x86_64-linux-gnu
解决思路就是把/usr/lib/x86_64-linux-gnu备份一下,重新复制一份过去。
于是,在本地新建虚拟机,装上ubuntu 20.10的系统,模拟故障,使用ubuntu 20.10 desktop版本的live cd模式启动。把硬盘挂载到/mnt目录,尝试恢复:

mv /mnt/usr/lib/x86_64-linux-gnu /mnt/usr/lib/x86_64-linux-gnubak
cp -rp /usr/lib/x86_64-linux-gnu /mnt/usr/lib
chroot /mnt

发现chroot不过去,怀疑是仍然有问题。于是,发现lib64下的ld-linux-x86-64.so.2文件也发生了变动。查看这个文件:

ll /lib64/ld-linux-x86-64.so.2 
lrwxrwxrwx 1 root root 32 Sep 15  2020 /lib64/ld-linux-x86-64.so.2 -> /lib/x86_64-linux-gnu/ld-2.32.so*

把这个文件也复制回去,因为原来是个软连接,这里直接简单粗暴的把源文件复制过去了

cp /lib/x86_64-linux-gnu/ld-2.32.so  /mnt/lib64/ld-linux-x86-64.so.2
chroot /mnt

根目录转化成功,实验命令可以正常执行。
于是去机房,关机、U盘启动,修复文件,搞定。

在运行过程中又发现,部分软件缺少文件,将 /usr/lib/x86_64-linux-gnubak/中的文件,复制但不替换回/usr/lib/x86_64-linux-gnu/

rsync -av --ignore-existing /usr/lib/x86_64-linux-gnubak/ /usr/lib/x86_64-linux-gnu/

当然,也可以在恢复 /usr/lib/x86_64-linux-gnu/时:

# 原来是mv,改为cp
cp -rp /mnt/usr/lib/x86_64-linux-gnu /mnt/usr/lib/x86_64-linux-gnubak
cp -rp /usr/lib/x86_64-linux-gnu/*  /mnt/usr/lib/x86_64-linux-gnu

这样,直接覆盖掉修改过的文件(没试过,盲猜的)

总结

  1. /usr/lib/x86_64-linux-gnu替换回原操作系统内容
  2. 替换回 /lib64/ld-linux-x86-64.so.2
  3. 将后期增加的/usr/lib/x86_64-linux-gnu下的文件,增量复制回去
  4. 执行命令前,一定要看一眼到底执行了什么。不要闭着眼操作
  5. 服务器能跑,不影响业务使用,就不要管他。
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值