彻底解决 "/lib64/libc.so.6: version `GLIBC_2.18' not found (required by /lib64/libstdc++.so.6)" 的问题

时间:2023-01-04 15:31:17

写在前面

本文属于step by step类型,请务必注意环境,本文无法保证在其他linux发行版上的可行性,也无法保证在CentOS其他版本上的可行性,如果不是CentOS7系统,本文升级办法仅供参考,请谨慎对待!!!

环境

# cat /etc/redhat-release 
CentOS Linux release 7.2.1511 (Core)

注意, 以下操作只能保证在CentOS 7系统(且没有升级过glibc)上的可行性, 其他系统没有验证

无风险升级

curl -O http://ftp.gnu.org/gnu/glibc/glibc-2.18.tar.gz
tar zxf glibc-2.18.tar.gz 
cd glibc-2.18/
mkdir build
cd build/
../configure --prefix=/usr #注意了,别修改路径
make -j2
make install

升级目标完成

折腾一下

折腾只是为了了解更多知识,请在实验环境(如虚拟机)中折腾,生产环境升级,按上面的 无风险升级 操作!!!

环境

# strings /usr/lib64/libc.so.6 | grep ^GLIBC_
GLIBC_2.2.5
GLIBC_2.2.6
GLIBC_2.3
GLIBC_2.3.2
GLIBC_2.3.3
GLIBC_2.3.4
GLIBC_2.4
GLIBC_2.5
GLIBC_2.6
GLIBC_2.7
GLIBC_2.8
GLIBC_2.9
GLIBC_2.10
GLIBC_2.11
GLIBC_2.12
GLIBC_2.13
GLIBC_2.14
GLIBC_2.15
GLIBC_2.16
GLIBC_2.17
GLIBC_PRIVATE
GLIBC_PRIVATE
GLIBC_2.8
GLIBC_2.3
GLIBC_2.5
GLIBC_2.4
GLIBC_2.9
GLIBC_2.7
GLIBC_2.6
GLIBC_2.3.2
GLIBC_2.3.4
GLIBC_2.3.3
GLIBC_2.15
GLIBC_2.14
GLIBC_2.11
GLIBC_2.16
GLIBC_2.10
GLIBC_2.17
GLIBC_2.12
GLIBC_2.13
GLIBC_2.2.5
GLIBC_2.2.6

没有GLIBC_2.18

编译glibc-2.18

curl -O http://ftp.gnu.org/gnu/glibc/glibc-2.18.tar.gz
tar zxf glibc-2.18.tar.gz 
cd glibc-2.18/
mkdir build
cd build/
../configure --prefix=/opt/glibc-2.18 #为了折腾,路径被修改了
make -j2
make install

cd /opt/glibc-2.18/lib

替换libc.so.6

折腾完后,再将libc.so.6还原为系统自带的版本,所以,替换前可以先备份一下,不备份直接做软链也是可以的,当然,折腾完了,也可以直接废弃这个系统,ld-linux-x86-64.so.2也是一样,啰嗦一句,折腾用的系统,可以先做个模板(镜像),来回重装系统太麻烦了

# ln -sf /opt/glibc-2.18/lib/libc-2.18.so /usr/lib64/libc.so.6
# ls
ls: relocation error: /lib64/libpthread.so.0: symbol __getrlimit, version GLIBC_PRIVATE not defined in file libc.so.6 with link time reference

LD_LIBRARY_PATH 未设置, /usr/lib64下的libpthread.so.0版本对不上

设置LD_LIBRARY_PATH

# export LD_LIBRARY_PATH=/opt/glibc-2.18/lib:/usr/lib64
# ls
ls: relocation error: /opt/glibc-2.18/lib/libc.so.6: symbol _dl_find_dso_for_object, version GLIBC_PRIVATE not defined in file ld-linux-x86-64.so.2 with link time reference

对应的动态链接库找到了, 但ld-linux.so版本对不上

替换ld-linux-x86-64.so.2

# ln -sf /opt/glibc-2.18/lib/ld-2.18.so /usr/lib64/ld-linux-x86-64.so.2
Segmentation fault (core dumped)

还是libc.so.6的原因

# LD_PRELOAD=/usr/lib64/libc-2.17.so ln -sf /opt/glibc-2.18/lib/ld-2.18.so /usr/lib64/ld-linux-x86-64.so.2
# ls
bin  etc  include  lib  libexec  sbin  share  var

OK

再次确认

# strings /usr/lib64/libc.so.6 | grep ^GLIBC_
GLIBC_2.2.5
GLIBC_2.2.6
GLIBC_2.3
GLIBC_2.3.2
GLIBC_2.3.3
GLIBC_2.3.4
GLIBC_2.4
GLIBC_2.5
GLIBC_2.6
GLIBC_2.7
GLIBC_2.8
GLIBC_2.9
GLIBC_2.10
GLIBC_2.11
GLIBC_2.12
GLIBC_2.13
GLIBC_2.14
GLIBC_2.15
GLIBC_2.16
GLIBC_2.17
GLIBC_2.18
GLIBC_PRIVATE
GLIBC_PRIVATE
GLIBC_2.8
GLIBC_2.3
GLIBC_2.5
GLIBC_2.4
GLIBC_2.9
GLIBC_2.7
GLIBC_2.6
GLIBC_2.3.2
GLIBC_2.3.4
GLIBC_2.3.3
GLIBC_2.18
GLIBC_2.15
GLIBC_2.14
GLIBC_2.11
GLIBC_2.16
GLIBC_2.10
GLIBC_2.17
GLIBC_2.12
GLIBC_2.13
GLIBC_2.2.5
GLIBC_2.2.6

GLIBC_2.18

善后处理

请将libc.so.6ld-linux-x86-64.so.2还原为系统自带的版本

知识点

  • 运行程序时, 系统默认使用的glibc库和动态链接器分别为:
[root@localhost glibc-2.18]# ls -l /usr/lib64/ | grep -E "libc.so|ld-linux"
lrwxrwxrwx.  1 root root       30 May 22 05:58 ld-linux-x86-64.so.2 -> /opt/glibc-2.18/lib/ld-2.18.so
lrwxrwxrwx.  1 root root       32 May 22 05:46 libc.so.6 -> /opt/glibc-2.18/lib/libc-2.18.so
  • 链接器加载动态链接库的顺序, 见man ld.so
When  resolving  library  dependencies,  the  dynamic  linker first inspects each dependency string to see if it contains a slash (this can occur if a library pathname containing slashes was specified at link time).  If a slash is found, then the dependency string is interpreted as a (relative or absolute) pathname, and the library is  loaded  using  that pathname.

If a library dependency does not contain a slash, then it is searched for in the following order:

o  (ELF only) Using the directories specified in the DT_RPATH dynamic section attribute of the binary if present and DT_RUNPATH attribute does not exist.  Use of DT_RPATH is dep-recated.

o  Using the environment variable LD_LIBRARY_PATH.  Except if the executable is a set-user-ID/set-group-ID binary, in which case it is ignored.

o  (ELF only) Using the directories specified in the DT_RUNPATH dynamic section attribute of the binary if present.

o  From the cache file /etc/ld.so.cache, which contains a compiled list of candidate libraries previously found in the augmented library path.  If, however, the binary was linked with  the  -z  nodeflib linker option, libraries in the default library paths are skipped.  Libraries installed in hardware capability directories (see below) are preferred to other libraries.

o  In the default path /lib, and then /usr/lib.  If the binary was linked with the -z nodeflib linker option, this step is skipped.
  • 指定搜索路径
    1. 在配置文件 /etc/ld.so.conf 中指定动态库搜索路径. 每次编辑完该文件后, 都必须运行命令 ldconfig 使修改后的配置生效 . /etc/ld.so.cache包含了在/etc/ld.so.conf中指定的目录中查找到所有连接库, 按顺序存储.
    2. 通过环境变量 LD_LIBRARY_PATH 指定动态库搜索路径.
    3. 在编译目标代码时指定该程序的动态库搜索路径. 通过 gcc 的参数 -Wl,-rpath 指定. 当指定多个动态库搜索路径时, 路径之间用冒号 ‘:’ 分隔. -Wl, 表示后面的参数将传给 link 程序 ld (因为 gcc 可能会自动调用ld ).

参考

动态库加载路径之RPATH与RUNPATH

其他

推荐一个关于 科学用脑 的软件,Linux上使用Pomodoro Technique(番茄工作法)软件