编写了一个小脚本,方便在不同版本 Linux 转移 c/c++程序,无需重新编译。

2019-05-23 11:37:17 +08:00
 mq4079

编写了一个小脚本,方便在不同版本 linux 转移 c/c++程序,无需重新编译。

依赖 patchelf 这个小工具,可从各个软件源上安装。

使用场景:我司 linux 开发环境有很多,debian 系和 redhat 系 系统的库都不能兼容,有时候想把在 ubuntu 上编译的一个程序放到 centos 上跑就要重新编译一下,很麻烦,于是写了下面这个小脚本,使用很简单,假设要打包的程序名叫 testexe,只需patchelf.sh testexe,会生成一个 testexe.tar.gz 的包包含了这个程序所需的所有 so 动态库,把这个包放到 centos 下解压,会解压出 testexe 和它的所有依赖的 so,so 文件单独放在__lib 开头的文件夹,这个 testexe 会在__lib*的文件夹里找它的动态库而不会在 /usr/下面找。原理很简单

#!/bin/sh
#echo "脚本$0"
#echo "第一个参数$1"
which patchelf > /dev/null 2>&1
if [ $? -ne 0 ]; then
    echo "需要安装 patchelf,使用:"
    echo "sudo yum install patchelf 或"
    echo "sudo apt-get install patchelf"
    exit 1
fi
if [ -z "$1" ]
then
    echo "请输入可执行程序名"
    exit 1
fi
if  !(file "$1" | grep -q "GNU/Linux")
then
    echo "$1 不是是可执行文件"
    exit 1
fi
PwdDir=`pwd`
if [ -w . ];then
    echo "将在当前目录:"$PwdDir"产生打包文件"
else
    echo "当前目录不可写"
fi
PackBuildDir=$PwdDir/__PackBuildDir__
mkdir $PackBuildDir
cp $1 $PackBuildDir
ExeName=${1##*/}
CopyExePath=$PackBuildDir/$ExeName

echo "打包的 exe 是:" $ExeName
LibDirName="__libs_"$ExeName"__"


mkdir $PackBuildDir/$LibDirName

for i in `ldd $1| awk -F ' ' '{print $3}'|grep '.so'`; do
cp -n "$i" $PackBuildDir/$LibDirName
done
cp /lib64/ld-linux-x86-64.so.2 $PackBuildDir/$LibDirName
#改变库加载路径
patchelf --set-rpath ./$LibDirName --force-rpath $CopyExePath
patchelf --set-interpreter ./$LibDirName/ld-linux-x86-64.so.2 $CopyExePath

#打包
cd $PackBuildDir
tar -zcvf $PwdDir/$ExeName.tar.gz ./$ExeName ./$LibDirName

cd $PwdDir
rm -rf $PackBuildDir


exit 0

3873 次点击
所在节点    Linux
9 条回复
zycpp
2019-05-23 14:33:24 +08:00
why not docker
KigKrazy
2019-05-23 14:40:08 +08:00
docker
liangzi
2019-05-23 14:44:50 +08:00
zypper 表示路过...
pmispig
2019-05-23 16:39:26 +08:00
我更想问这么折腾,为何不用静态链接?
zonyitoo
2019-05-23 19:47:16 +08:00
楼上已经讲出了最根本的问题:为什么不用静态链接?
codehz
2019-05-23 19:52:10 +08:00
@zonyitoo #5 glibc 静态链接坑特别多。。。还有一些第三方库要静态链接也比较麻烦
codehz
2019-05-23 19:55:33 +08:00
另外其实这样打包也不是很稳,glibc 在使用名字查询等函数时,会 dlopen 一个硬编码的 so 文件。。然后在其他系统上可能会有冲突。。。
我折腾的一个方法是把这些 nss 相关的库也一并复制了,然后用 chroot 等方法去跑。。。
https://github.com/codehz/nsroot/wiki/Binary-Packager-for-archlinux
mq4079
2019-05-23 21:11:15 +08:00
@codehz 是的,我就是 glic 和 phread 静态链接搞不定才用这种方法的
liangzi
2019-05-30 21:15:30 +08:00
ld-linux-x86-64.so.2 在我这里是个软连接 连接到当前目录下

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/566890

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX