glibc 版本異常

事情起因

發(fā)現(xiàn)有一臺(tái)物理機(jī)只能連接同一個(gè)網(wǎng)段的公網(wǎng),不能訪問如百度,dns服務(wù)器也ping不通,我就想裝個(gè)traceroute 看看是哪一步的原因,由于這臺(tái)機(jī)器不能聯(lián)網(wǎng),于是就打算從隔壁機(jī)器下載deb包,到這個(gè)機(jī)器上安裝。于是:

# 獲取依賴,并下載
apt-rdepends traceroute | grep -v "^ " | xargs sudo apt-get download
# 打包
tar zcvf traceroute.tgz traceroute/
# 遠(yuǎn)程復(fù)制
scp <>
# 解壓
tar zxvf traceroute.tgz 
# 安裝
cd traceroute&&dpkg -i *.deb

一氣呵成,問題來了,所有命令都用不了了,報(bào)錯(cuò)/lib/x86_64-linux-gnu/libc.so.6: version 'GLIBC_2.30' not found (required by /lib/x86_64-linux-gnu/libselinux.so.1)
后來發(fā)現(xiàn),隔壁機(jī)器跟這個(gè)機(jī)器不是同一個(gè)版本的操作系統(tǒng),而且這些安裝包里包含: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。好好好。只能怨我眼瞎。犯了這么低級(jí)的錯(cuò)誤。
更離譜的來了,因?yàn)槲沂莿倎磉@家公司,發(fā)現(xiàn)這個(gè)k8s集群的部分woker節(jié)點(diǎn)情況如下:

   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

好巧不巧,我操作的就是這個(gè) ubuntu 20.10。這個(gè)版本從發(fā)布到中止維護(hù)僅有9個(gè)月的時(shí)間。都是前人挖的坑啊。
此情此景,我只能說 k8s 牛逼,不挑食。
言歸正傳。現(xiàn)在什么命令都用不了。

自救過程

現(xiàn)在已經(jīng)打開的ssh是沒有斷開的,但是新的ssh已經(jīng)連接不了了。根據(jù)網(wǎng)上的方法:
上傳20.10用的glibc版本的 libc-2.32.so

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

然而,并沒有什么用。于此同時(shí),我還手賤的打算復(fù)制一個(gè)ssh連接,好家伙,windterm直接閃退。
那沒有辦法了,就只能去機(jī)房操作了。

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

這里使用docker的 layer 機(jī)制,就能很明顯的看到那些文件發(fā)生了改變

# 運(yùn)行一個(gè)ubuntu 20.10的容器
docker run -it --name ubunt-2010 -v /root:/data ubuntu:20.10 bash
# 安裝相關(guān)的包
cd /data/traceroute
dpkg -i *.deb
# 發(fā)現(xiàn)問題與線上問題一致
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)

接下來另起一個(gè)窗口:

docker inspect ubuntu-2010 --format '{{.GraphDriver.Data.UpperDir}}'
# cd 到這個(gè)目錄
cd <上一步輸出結(jié)果>
# 查看哪些文件夾發(fā)生了改變
tree
# 這里發(fā)現(xiàn)很多文件都改變了,于是只看看哪些目錄
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

在啟動(dòng)一個(gè)新的ubuntu 20.10的容器,對(duì)比發(fā)現(xiàn) /usr/lib/gcc/x86_64-linux-gnu目錄是新增的,新增一般影響不大。主要變動(dòng)就是/usr/lib/x86_64-linux-gnu。
解決思路就是把/usr/lib/x86_64-linux-gnu備份一下,重新復(fù)制一份過去。
于是,在本地新建虛擬機(jī),裝上ubuntu 20.10的系統(tǒng),模擬故障,使用ubuntu 20.10 desktop版本的live cd模式啟動(dòng)。把硬盤掛載到/mnt目錄,嘗試恢復(fù):

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

發(fā)現(xiàn)chroot不過去,懷疑是仍然有問題。于是,發(fā)現(xiàn)lib64下的ld-linux-x86-64.so.2文件也發(fā)生了變動(dòng)。查看這個(gè)文件:

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*

把這個(gè)文件也復(fù)制回去,因?yàn)樵瓉硎莻€(gè)軟連接,這里直接簡(jiǎn)單粗暴的把源文件復(fù)制過去了

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

根目錄轉(zhuǎn)化成功,實(shí)驗(yàn)命令可以正常執(zhí)行。
于是去機(jī)房,關(guān)機(jī)、U盤啟動(dòng),修復(fù)文件,搞定。

在運(yùn)行過程中又發(fā)現(xiàn),部分軟件缺少文件,將/usr/lib/x86_64-linux-gnubak/中的文件,復(fù)制但不替換回/usr/lib/x86_64-linux-gnu/

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

當(dāng)然,也可以在恢復(fù)/usr/lib/x86_64-linux-gnu/時(shí):

# 原來是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

這樣,直接覆蓋掉修改過的文件(沒試過,盲猜的)

總結(jié)

  1. /usr/lib/x86_64-linux-gnu替換回原操作系統(tǒng)內(nèi)容
  2. 替換回 /lib64/ld-linux-x86-64.so.2
  3. 將后期增加的/usr/lib/x86_64-linux-gnu下的文件,增量復(fù)制回去
  4. 執(zhí)行命令前,一定要看一眼到底執(zhí)行了什么。不要閉著眼操作
  5. 服務(wù)器能跑,不影響業(yè)務(wù)使用,就不要管他。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容