如题,不要改系统的glibc版本,否则!你的系统可能崩掉!
踩坑经历
因为Ubuntu20.04(GBLIC 2.31)和Ubuntu16.04(GLIBC 2.23)版本不兼容。在20.04上面编译的二进制无法在16.04上面运行。报错,
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04.2 LTS
Release: 16.04
Codename: xenial
$ ./feeder_handler
./feeder_handler: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by ./feeder_handler)
./feeder_handler: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by ./libmdl_api.so)
因为feeder_handler是在20.04上面编译的。你可以通过以下方法查看glibc版本,
$ ldd --version | head -1
ldd (Ubuntu GLIBC 2.23-0ubuntu11.3) 2.23
$ strings /lib/x86_64-linux-gnu/libm.so.6 | grep GLIBC
GLIBC_2.2.5
GLIBC_2.4
GLIBC_2.15
GLIBC_2.18
GLIBC_2.23
GLIBC_PRIVATE
可见,系统上的glibc是2.23版本。而二进制文件需要glibc2.29版本。解决方法有二:
- 把源码放到16.04的机器上编译
- 在16.04上装一个glibc2.29,通过patchelf修改动态库指向
对于频繁更新代码,编译,放到目标机器上跑的任务来说,每次都要patchelf有点过于恼人。两种方案可参考:
- 如何安装其他版本的glibc:https://stackoverflow.com/a/73188338
- 如何修改动态库指向新的glibc版本:https://stackoverflow.com/a/851229
Attention
但是,千万注意,不要动系统的glibc相关文件!否则,
很可能必定会把系统弄崩掉。
我就替换了一个符号链接,将libpthread.so.0换了一个指向就引发了雪崩。
ll /lib/x86_64-linux-gnu/libpthread*
-rwxr-xr-x 1 root root 157224 Jan 29 22:41 /lib/x86_64-linux-gnu/libpthread-2.31.so*
-rw-r--r-- 1 root root 6590210 Jan 29 22:41 /lib/x86_64-linux-gnu/libpthread.a
lrwxrwxrwx 1 root root 37 Jan 29 22:41 /lib/x86_64-linux-gnu/libpthread.so -> /lib/x86_64-linux-gnu/libpthread.so.0*
lrwxrwxrwx 1 root root 18 Mar 7 09:23 /lib/x86_64-linux-gnu/libpthread.so.0 -> libpthread-2.31.so*
可以看到libpthread.so.0指向正确版本的libpthread-2.31.so,如果这里改为指向一个低版本的动态库。你会发现一连串奇怪的问题接踵而来,连ls
都不能正常工作。不能切用户,不能sudo,无法校验密码(输入用户名直接报鉴权失败)。重启一下立马启不动,无法正常开机。进入修复模式,直接报kernel panic. 下面欣赏一部分截图,
从上面一些截图中可见端倪,系统的很多命令依赖这个动态库,而你改了不兼容的版本,导致寻址错误,找不到对应的符号,大部分程序都会崩溃。据同事说低版本指向高版本是ok的(按时高版本兼容低版本),但是who knows!万一替换了一个不兼容的版本,GG!
修复建议
找一个bootable的live cd,比如archliux的安装盘,进去之后挂在相应目录,把软连接指向正确的文件即可。