技术解析
编写了一个小脚本,方便在不同版本 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