LD_LIBRARY_PATH具有相同名称的库时的动态库首选项

时间:2016-06-09 10:57:44

标签: oracle gcc shared-libraries dynamic-linking

我有一个可执行文件和一个.so文件,它使用不同版本的Oracle Instant Client库。它们与不同版本兼容,我必须同时使用它们。

可执行文件使用版本11 - 它链接到使用“libclntsh.so.11.1”的.so文件 - 版本是硬编码的,我无法修改.so文件。

ldd Executable_name
    linux-vdso.so.1 =>  (0x00007ffffe7fe000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fbb33e80000)
    libdx_t.so => not found
    libudr_t.so => not found
    libnsl.so.1 => /lib64/libnsl.so.1 (0x00007fbb33c66000)
    **libclntsh.so.11.1** => not found
    libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007fbb3395e000)
    libm.so.6 => /lib64/libm.so.6 (0x00007fbb3365c000)
    libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fbb33445000)
    libc.so.6 => /lib64/libc.so.6 (0x00007fbb33084000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fbb340aa000)

.so文件正在使用版本12,它正在使用dlopen

ldd libOracleClient.so
    linux-vdso.so.1 =>  (0x00007fff705a2000)
    libclntsh.so.12.1 => not found
    libocci.so.12.1 => not found
    libnnz12.so => not found
    libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007fe8d6d49000)
    libm.so.6 => /lib64/libm.so.6 (0x00007fe8d6a46000)
    libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fe8d6830000)
    libc.so.6 => /lib64/libc.so.6 (0x00007fe8d646f000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fe8d72e4000)

我已经成功编译了我的代码。我为这两个版本的Oracle Instant Client创建了两个目录,并将它们都添加到LD_LIBRARY_PATH。

问题是在两个Oracle Instant Client 11和12目录中有一些.so文件具有相同的名称。

Oracle Instant Client 11库: -

  

libclntsh.so libclntsh.so.11.1 libnnz11.so libocci.so libocci.so.11.1 libociei.so libocijdbc11.so ojdbc5.jar ojdbc6.jar xstreams.jar

Oracle Instant Client 12库: -

  

libclntshcore.so.12.1 libclntsh.so.12.1 libmql1.so libocci.so.12.1 libociei.so libons.so ojdbc6.jar xstreams.jar   libclntsh.so libipc1.so libnnz12.so libocci.so_bkp libocijdbc12.so liboramysql12.so ojdbc7.jar

具有相同名称的库:libociei.so等。

现在,情况是来自Oracle 12客户端的.so文件在内部调用了一个存在于Oracle 11客户端目录中的.so文件。将使用哪个.so,因为在LD_LIBRARY_PATH中都存在?

1 个答案:

答案 0 :(得分:0)

一个相当简单的方法是让您的LD_LIBRARY_PATH仅引用当前版本的12c库位置,并从中移除11g路径。

然后有一个包装器脚本(或shell函数)设置11g路径并调用可执行文件,比如my_exe_wrapper

export LD_LIBRARY_PATH=/path/to/instant_client_12_1
# add anything else you need in that variable, except the 11g path
/path/to/original_exe

添加别名,以便您仍然可以通过原始名称引用它:

alias -x original_exe=/path/to/my_exe_wrapper

现在当你运行original_exe时,它将调用包装器脚本,它将设置环境变量并调用真正的可执行文件。这将无法查看12c库,因为它们的路径不再被搜索。反过来说,其他一切 - 包括任何使用libOracleClient.so - 将无法看到11g库。

如果您的LD_LIBRARY_PATH包含大量条目,并且您不想从头开始重新创建它,并且如果11g和12c库位置的路径相似,则可以使用{{1}仅替换该段。如果你把它们放在sed/opt/instant_client_11_2之下,你的包装器可以这样做:

/opt/instant_client_12_1