我的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包含许多必须匹配的部分(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。
当我想在Ubuntu precise (glibc-2.15)上运行chromium浏览器时,我得到了
(典型的)消息“…libc.so。6:版本' GLIBC_2.19'未找到…"
我考虑了这样一个事实,即文件不是永久需要的,而只是在开始时需要。
因此,我收集了浏览器和sudo所需的文件,并创建了一个mini-glibc-2.19-
环境,启动浏览器,然后将原始文件复制回来
一次。所需的文件在RAM中,原始的glibc是相同的。
as root
the files (*-2.15.so) already exist
Mkdir -p /glibc-2.19/i386-linux-gnu
/glibc-2.19/ld-linux.so.2 -> /glibc-2.19/i386-linux-gnu/ld-2.19.so
/glibc-2.19/i386-linux-gnu/libc.so.6 -> libc-2.19.so
/glibc-2.19/i386-linux-gnu/libdl.so.2 -> libdl-2.19.so
/glibc-2.19/i386-linux-gnu/libpthread.so.0 -> libpthread-2.19.so
Mkdir -p /glibc-2.15/i386-linux-gnu
/glibc-2.15/ld-linux.so.2 -> (/glibc-2.15/i386-linux-gnu/ld-2.15.so)
/glibc-2.15/i386-linux-gnu/libc.so.6 -> (libc-2.15.so)
/glibc-2.15/i386-linux-gnu/libdl.so.2 -> (libdl-2.15.so)
/glibc-2.15/i386-linux-gnu/libpthread.so.0 -> (libpthread-2.15.so)
运行浏览器的脚本:
#!/bin/sh
sudo cp -r /glibc-2.19/* /lib
/path/to/the/browser &
sleep 1
sudo cp -r /glibc-2.15/* /lib
sudo rm -r /lib/i386-linux-gnu/*-2.19.so
首先,每个动态链接程序最重要的依赖项是链接器。所有这些库必须与链接器的版本相匹配。
让我们举一个简单的例子:我有一个newset ubuntu系统,在那里我运行一些程序(在我的情况下,它是D编译器- ldc2)。我想在旧的CentOS上运行它,但是由于旧的glibc库,这是不可能的。我得到了
ldc2-1.5.0-linux-x86_64/bin/ldc2: /lib64/libc.so.6: version `GLIBC_2.15' not found (required by ldc2-1.5.0-linux-x86_64/bin/ldc2)
ldc2-1.5.0-linux-x86_64/bin/ldc2: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by ldc2-1.5.0-linux-x86_64/bin/ldc2)
我必须将所有依赖从ubuntu复制到centos。
正确的方法如下:
首先,让我们检查所有依赖项:
ldd ldc2-1.5.0-linux-x86_64/bin/ldc2
linux-vdso.so.1 => (0x00007ffebad3f000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f965f597000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f965f378000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f965f15b000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f965ef57000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f965ec01000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f965e9ea000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f965e60a000)
/lib64/ld-linux-x86-64.so.2 (0x00007f965f79f000)
linux-vdso.so。1不是一个真正的库,我们不必关心它。
/ lib64 / ld - linux - x86 - 64.。2是链接器,Linux使用它将可执行文件与所有动态库链接起来。
其余的文件都是真正的库,所有这些文件和链接器都必须复制到centos中的某个地方。
让我们假设所有的库和链接器都在“/mylibs”目录下。
ld - linux - x86 - 64.。2 -我已经说过了-是连接器。它不是动态库,而是静态可执行文件。您可以运行它并查看它甚至有一些参数,例如library-path(我将返回它)。
在linux上,动态链接的程序可以只根据它的名字来发布
/bin/ldc2
Linux将这样的程序加载到RAM中,并检查为它设置了哪个链接器。通常,在64位系统上,它是/lib64/ld-linux-x86-64.so.2(在您的文件系统中,它是到实际可执行文件的符号链接)。
然后linux运行链接器并加载动态库。
你也可以稍微改变一下,这样做:
/mylibs/ld-linux-x86-64.so.2 /bin/ldc2
它是强迫linux使用特定链接器的方法。
现在我们可以回到前面提到的参数——library-path
/mylibs/ld-linux-x86-64.so.2 --library-path /mylibs /bin/ldc2
它将运行ldc2并从/mylibs加载动态库。
这是使用选择(不是系统默认)库调用可执行文件的方法。
“受雇的俄罗斯人”是最好的答案之一,我认为所有其他建议的答案可能都行不通。原因很简单,因为当应用程序第一次创建时,它需要的所有api都在编译时解析。使用"ldd"你可以看到所有静态链接的依赖项:
ldd /usr/lib/firefox/firefox
linux-vdso.so.1 => (0x00007ffd5c5f0000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f727e708000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f727e500000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f727e1f8000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f727def0000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f727db28000)
/lib64/ld-linux-x86-64.so.2 (0x00007f727eb78000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f727d910000)
但在运行时,firefox也会加载许多其他动态库,例如(对于firefox)有许多“glib”标记的库加载(即使静态链接没有):
/usr/lib/x86_64-linux-gnu/libdbus-glib-1.so.2.2.2
/lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0
/usr/lib/x86_64-linux-gnu/libavahi-glib.so.1.0.2
很多时候,您可以看到一个版本的名称被软链接到另一个版本。例如:
lrwxrwxrwx 1 root root 23 Dec 21 2014 libdbus-glib-1.so.2 -> libdbus-glib-1.so.2.2.2
-rw-r--r-- 1 root root 160832 Mar 1 2013 libdbus-glib-1.so.2.2.2
因此,这意味着在一个系统中存在不同版本的“库”——这不是问题,因为它们是同一个文件,而且当应用程序具有多个版本依赖关系时,它将提供兼容性。
因此,在系统级别上,所有的库几乎都是相互依赖的,仅仅通过操纵LD_PRELOAD或LD_LIBRARY_PATH来改变库的加载优先级是没有帮助的——即使它可以加载,运行时它仍然可能崩溃。
http://lightofdawn.org/wiki/wiki.cgi/-wiki/NewAppsOnOldGlibc
最好的替代方案是chroot (ER简要提到过):但为此你需要重新创建原始二进制执行的整个环境——通常从/lib, /usr/lib/x86等开始。你可以使用“builroot”,或者YoctoProject,或者直接从现有的发行版环境中tar。(比如Fedora/Suse等)。