在相对较新的发行版上编译的程序,部署在老发行版上多半会出问题,
静态链接并不是万能的解决方案,而动态链接的执行文件遇到的最常见的问题是依赖GLIBC的版本高于目标系统的版本。
在一个老版本系统上重新编译并不总是可行,一来要重新搭配环境比较麻烦,二来可能压根就没有源码能重新编译。
我在stack overflow上看到了一种解决方案:
首先,将libc.so等核心库跟其他依赖的库一并打包还不够,因为ld-2.14.so和libc必须要匹配,所以/lib/ld-2.14.so也要一并拷贝过来。
用ldd检查执行文件的递归依赖关系,将所有依赖的so文件拷贝到例如lib目录,执行的时候需要显式的用ld-2.14.so调用:
/path/to/ld-2.14.so --library-path /path/to/lib /path/to/executable
但是stack overflow上提到一点是如果程序根据argv[0]来重新exec自己的话,会有问题。
但是我用一个简单的c程序测试argv[0]并没有发生变化,不知道是不是我的理解不正确。
另外,即便是与参数形式运行执行文件,但/path/to/executable必须使用相对或绝对路径,省略路径会报错。
这里还可以用patchelf设置RPATH
patchelf --set-rpath '$ORIGIN/relative/to/lib' /path/to/executable
然后把所有依赖的共享库的RPATH设置为$ORIGIN(如果它们都放在同一目录下的话)
这样可用
/path/to/ld-2.14.so /path/to/executable
省略掉--library-path参数