我的linux (SLES-8)服务器目前有glibc-2.2.5-235,但我有一个程序不能在这个版本上工作,需要glibc-2.3.3。

是否可以在同一台主机上安装多个glibc ?

这是我在旧的glibc上运行程序时得到的错误:

./myapp: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by ./myapp)
./myapp: /lib/i686/libpthread.so.0: version `GLIBC_2.3.2' not found (required by ./myapp)
./myapp: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by ./libxerces-c.so.27)
./myapp: /lib/ld-linux.so.2: version `GLIBC_2.3' not found (required by ./libstdc++.so.6)
./myapp: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by ./libstdc++.so.6)

所以我创建了一个名为newglibc的新目录,并复制了以下文件:

libpthread.so.0
libm.so.6
libc.so.6
ld-2.3.3.so
ld-linux.so.2 -> ld-2.3.3.so

and

export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH

但是我得到一个错误:

./myapp: /lib/ld-linux.so.2: version `GLIBC_PRIVATE' not found (required by ./newglibc/libpthread.so.0)
./myapp: /lib/ld-linux.so.2: version `GLIBC_2.3' not found (required by libstdc++.so.6)
./myapp: /lib/ld-linux.so.2: version `GLIBC_PRIVATE' not found (required by ./newglibc/libm.so.6)
./myapp: /lib/ld-linux.so.2: version `GLIBC_2.3' not found (required by ./newglibc/libc.so.6)
./myapp: /lib/ld-linux.so.2: version `GLIBC_PRIVATE' not found (required by ./newglibc/libc.so.6)

因此,它们似乎仍然链接到/lib,而不是从我放置它们的位置拾取。


当前回答

如果仔细观察第二个输出,可以看到使用了库的新位置。可能仍然有作为glibc一部分的库丢失。

我还认为您的程序使用的所有库都应该根据该glibc版本进行编译。如果您可以访问程序的源代码,那么重新编译似乎是最好的解决方案。

其他回答

这个问题老了,其他答案也老了。“受雇的俄罗斯人”的回答是非常好的和信息丰富的,但它只有在你有源代码的情况下才有效。如果你不这样做,那时候的选择是非常棘手的。幸运的是,现在我们对这个问题有了一个简单的解决方案(正如他在回复中评论的那样),使用patchelf。你所要做的就是:

$ ./patchelf --set-interpreter /path/to/newglibc/ld-linux.so.2 --set-rpath /path/to/newglibc/ myapp

在那之后,你可以执行你的文件:

$ ./myapp

No need to chroot or manually edit binaries, thankfully. But remember to backup your binary before patching it, if you're not sure what you're doing, because it modifies your binary file. After you patch it, you can't restore the old path to interpreter/rpath. If it doesn't work, you'll have to keep patching it until you find the path that will actually work... Well, it doesn't have to be a trial-and-error process. For example, in OP's example, he needed GLIBC_2.3, so you can easily find which lib provides that version using strings:

$ strings /lib/i686/libc.so.6 | grep GLIBC_2.3
$ strings /path/to/newglib/libc.so.6 | grep GLIBC_2.3

理论上,第一个grep会是空的,因为系统libc没有他想要的版本,而第二个grep应该输出glibc2.3,因为它有myapp正在使用的版本,所以我们知道可以使用该路径修补我们的二进制文件。如果你得到一个分割错误,阅读末尾的说明。

当你尝试在linux中运行二进制文件时,二进制文件会尝试加载链接器,然后加载库,它们都应该在路径和/或在正确的位置。如果你的问题是链接器,你想知道你的二进制文件在寻找哪个路径,你可以用这个命令来找到:

$ readelf -l myapp | grep interpreter
  [Requesting program interpreter: /lib/ld-linux.so.2]                                                                                                                                                                                   

如果你的问题是库,命令会给你正在使用的库:

$ readelf -d myapp | grep Shared
$ ldd myapp 

这将列出二进制文件需要的库,但您可能已经知道有问题的库,因为它们已经产生错误,就像OP的情况一样。

"patchelf" works for many different problems that you may encounter while trying to run a program, related to these 2 problems. For example, if you get: ELF file OS ABI invalid, it may be fixed by setting a new loader (the --set-interpreter part of the command) as I explain here. Another example is for the problem of getting No such file or directory when you run a file that is there and executable, as exemplified here. In that particular case, OP was missing a link to the loader, but maybe in your case you don't have root access and can't create the link. Setting a new interpreter would solve your problem.

感谢受雇于俄罗斯和Michael Pankov的洞察力和解决方案!


注意分割错误:你可能在myapp使用几个库的情况下,他们中的大多数是可以的,但有些不是;然后你修补它到一个新的目录,你得到分割错误。当你修补你的二进制文件时,你改变了几个库的路径,即使有些原本在不同的路径。看看下面的例子:

$ ldd myapp
./myapp: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by ./myapp)
./myapp: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by ./myapp)
        linux-vdso.so.1 =>  (0x00007fffb167c000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f9a9aad2000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f9a9a8ce000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f9a9a6af000)
        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f9a9a3ab000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9a99fe6000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f9a9adeb000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f9a99dcf000)

Note that most libs are in /lib/x86_64-linux-gnu/ but the problematic one (libstdc++.so.6) is on /usr/lib/x86_64-linux-gnu. After I patchelf'ed myapp to point to /path/to/mylibs, I got segmentation fault. For some reason, the libs are not totally compatible with the binary. Since myapp didn't complain about the original libs, I copied them from /lib/x86_64-linux-gnu/ to /path/to/mylibs2, and I also copied libstdc++.so.6 from /path/to/mylibs there. Then I patchelf'ed it to /path/to/mylibs2, and myapp works now. If your binary uses different libs, and you have different versions, it might happen that you can't fix your situation. :( But if it's possible, mixing libs might be the way. It's not ideal, but maybe it will work. Good luck!

在同一个系统上有多个glibc版本是很可能的(我们每天都这样做)。

但是,您需要知道glibc包含许多必须匹配的部分(200多个共享库)。其中一个是ld-linux.so。2,它必须匹配lib .so。6,否则你会看到你所看到的错误。

linux.so的绝对路径。2是在链接时硬编码到可执行文件中,并且在链接完成后不能轻易更改(更新:可以用patchelf完成;请看下面的答案)。

要构建一个可以与新的glibc一起工作的可执行文件,请执行以下操作:

g++ main.o -o myapp ... \
   -Wl,--rpath=/path/to/newglibc \
   -Wl,--dynamic-linker=/path/to/newglibc/ld-linux.so.2

-rpath linker选项将使运行时加载器搜索/path/to/newglibc中的库(因此您不必在运行它之前设置LD_LIBRARY_PATH),而-dynamic-linker选项将“烤”路径以纠正ld-linux.so。2 .进入应用。

如果不能重新链接myapp应用程序(例如,因为它是第三方二进制文件),并不是全部都丢失了,但它会变得更棘手。一种解决方案是为它设置适当的chroot环境。另一种可能是使用rtldi和二进制编辑器。更新:或者你可以使用patchelf。

@msb给出了一个安全的解决方案。

我在CentOS 6.5的conda环境中导入tensorflow作为tf时遇到了这个问题,CentOS 6.5只有glibc-2.12。

ImportError: /lib64/libc.so.6: version `GLIBC_2.16' not found (required by /home/

我想提供一些细节:

首先将glibc安装到主目录:

mkdir ~/glibc-install; cd ~/glibc-install
wget http://ftp.gnu.org/gnu/glibc/glibc-2.17.tar.gz
tar -zxvf glibc-2.17.tar.gz
cd glibc-2.17
mkdir build
cd build
../configure --prefix=/home/myself/opt/glibc-2.17  # <-- where you install new glibc
make -j<number of CPU Cores>  # You can find your <number of CPU Cores> by using **nproc** command
make install

其次,按照同样的方法安装patchelf;

第三,给你的Python打补丁:

[myself@nfkd ~]$ patchelf --set-interpreter /home/myself/opt/glibc-2.17/lib/ld-linux-x86-64.so.2 --set-rpath /home/myself/opt/glibc-2.17/lib/ /home/myself/miniconda3/envs/tensorflow/bin/python

正如@msb提到的

现在我可以在CentOS 6.5中使用tensorflow-2.0 alpha。

裁判:https://serverkurma.com/linux/how-to-update-glibc-newer-version-on-centos-6-x/

你可以考虑使用Nix http://nixos.org/nix/吗?

Nix支持多用户包管理:多个用户可以共享一个 普通Nix存储安全,不需要有root权限即可 安装软件,并可以安装和使用不同版本的一个 包中。

如果仔细观察第二个输出,可以看到使用了库的新位置。可能仍然有作为glibc一部分的库丢失。

我还认为您的程序使用的所有库都应该根据该glibc版本进行编译。如果您可以访问程序的源代码,那么重新编译似乎是最好的解决方案。