因项目需求,需要在多台服务器进行项目部署,当项目复杂依赖项过多时还需要考虑动态库依赖的问题。
1、开发机准备依赖环境动态库
以可执行程序 AIServer 例,
-
1、使用
ldd AIServer
查看依赖项ubuntu@ubuntu-server:/home//AIServer/bin$ ldd AIServer libswscale.so.5 => /lib/x86_64-linux-gnu/libswscale.so.5 (0x00007fb171fe2000) libavcodec.so.58 => /lib/x86_64-linux-gnu/libavcodec.so.58 (0x00007fb170a00000) libavutil.so.56 => /lib/x86_64-linux-gnu/libavutil.so.56 (0x00007fb17073c000) libavformat.so.58 => /lib/x86_64-linux-gnu/libavformat.so.58 (0x00007fb1704b3000) libswresample.so.3 => /lib/x86_64-linux-gnu/libswresample.so.3 (0x00007fb16d74d000)
-
2、保留so的完整文件路径
执行命令ldd AIServer | awk '{if (match($3,"/")) {print $3}}'
, 将前述控制台输出每一行的第3列进行以“/”匹配,若成功则打印该列对应so的完整路径。ubuntu@ubuntu-server:/home//AIServer/bin$ ldd AIServer | awk '{if (match($3,"/")) {print $3}}' /lib/x86_64-linux-gnu/libswscale.so.5 /lib/x86_64-linux-gnu/libavcodec.so.58 /lib/x86_64-linux-gnu/libavutil.so.56 /lib/x86_64-linux-gnu/libavformat.so.58 /lib/x86_64-linux-gnu/libswresample.so.3
-
3、拷贝所有依赖so到指定目录
当so较小时,直接手动依次拷贝so文件即可。当so较多,且有可能是软链接时,使用脚本处理。
创建 test.sh 脚本:deplist=$( ldd $1 | awk '{if (match($3,"/")){ print $3}}' ) cp -L -n $deplist $2
参数 -L 表示拷贝文件(如果是软链接,会拷贝到最终的文件); -n 表示不覆盖已有文件。
将AIServer依赖的动态库拷贝到目标目录/tmp/lib, 执行命令
#sudo ./test.sh AIServer /tmp/lib/
2、动态库链接目录设置
部署时,常规方式是将so放入到系统、用户链接库目录中,如 /lib,/usr/lib 和 /usr/local/lib 等。 若so较少时也可以直接放在可执行文件的目录下。
这里考虑so较多的情况,
-
完全拷贝到系统目录
如果开发机和部署机器环境相同,直接复制并无问题。 如果部署机有修改的特殊库、或者系统不同,直接复制轻则导致其他程序异常,重则系统崩溃,例如我们前面检查AIServer的依赖项有 libc.so.6等系统底层库。 如果要复制,要避免覆盖系统已有的库。
-
在
/etc/profile
中 对LD_LIBRARY_PATH
追加查找动态库目录这种方式修改后对该用户有效,重启依然有效。先用 echo 查看当前链接库目录。
$ echo $LD_LIBRARY_PATH :/usr/local/cuda-11.2/lib64:/usr/local/lib
对
/etc/profile
追加一行目录,并执行source /etc/profile
生效修改。export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/home/ubuntu/tmp/lib"
再次echo查看结果
$ echo $LD_LIBRARY_PATH :/usr/local/cuda-11.2/lib64:/usr/local/lib:/home/ubuntu/tmp/lib
-
临时追加
LD_LIBRARY_PATH
查找动态库目录运行程序前,控制台执行
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/home/ubuntu/tmp/lib"
命令,当前修改仅对运行shell有效。
3、测试
在当前目录下,有可执行文件app,依赖库为 dst/libmylib.so,运行结果为输出一行文字。
$ tree -L 2
├── app
├── dst
└── libmylib.so
直接执行时,结果如下
$ ./app
./app: error while loading shared libraries: libmylib.so: cannot open shared object file: No such file or directory
为方便运行,执行脚本 run_app.sh
, 结果如下
$ cat run_app.sh
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:./dst"
./app
$ ./run_app.sh
Hello, from mylib!
如果在其他目录运行时,需要在sh文件中填写完整路径。