V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
mq4079
V2EX  ›  Linux

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

  •  
  •   mq4079 · 2019-05-23 11:37:17 +08:00 · 3880 次点击
    这是一个创建于 2016 天前的主题,其中的信息可能已经有所发展或是发生改变。

    编写了一个小脚本,方便在不同版本 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
    
    
    9 条回复    2019-05-30 21:15:30 +08:00
    zycpp
        1
    zycpp  
       2019-05-23 14:33:24 +08:00 via iPhone
    why not docker
    KigKrazy
        2
    KigKrazy  
       2019-05-23 14:40:08 +08:00
    docker
    liangzi
        3
    liangzi  
       2019-05-23 14:44:50 +08:00 via Android
    zypper 表示路过...
    pmispig
        4
    pmispig  
       2019-05-23 16:39:26 +08:00
    我更想问这么折腾,为何不用静态链接?
    zonyitoo
        5
    zonyitoo  
       2019-05-23 19:47:16 +08:00
    楼上已经讲出了最根本的问题:为什么不用静态链接?
    codehz
        6
    codehz  
       2019-05-23 19:52:10 +08:00
    @zonyitoo #5 glibc 静态链接坑特别多。。。还有一些第三方库要静态链接也比较麻烦
    codehz
        7
    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
        8
    mq4079  
    OP
       2019-05-23 21:11:15 +08:00
    @codehz 是的,我就是 glic 和 phread 静态链接搞不定才用这种方法的
    liangzi
        9
    liangzi  
       2019-05-30 21:15:30 +08:00 via Android
    ld-linux-x86-64.so.2 在我这里是个软连接 连接到当前目录下
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3282 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 12:42 · PVG 20:42 · LAX 04:42 · JFK 07:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.