利用ldd打造Linux下的绿色软件包

来源:互联网 发布:ps淘宝美工修图视频 编辑:程序博客网 时间:2024/05/21 09:50

【原文:http://www.kongch.com/2010/06/ldd-linux-green-software/】

题记:其实这个想法来源于一个同事在之前公司的经验,感觉不错,记下来以免忘记。在云泛滥的今天,如何在云上快速部署应用其实是一个很有意思的话题。这种方法在我看来除了安装包比较大坨这一缺点之外,非常适合用来部署云应用。

众所周知绿色软件是windows下的一个概念,指的是仅仅一个文件夹硬copy过来就可以运行的软件,卸载时也同理:删除这个文件夹即可。说白了就是不会向系统文件夹、注册表这些地方乱丢东西的软件。

Linux下安装软件通常是编译安装,不同发行版本也有自己的二进制安装包,例如RedHat的rpm、Ubuntu的deb等。安装的最终结果往往也是向/usr/bin, /usr/lib, /usr/sbin…等诸如此类的文件夹下放上自己需要的东东。二进制包安装的话,卸载起来倒是不麻烦,但如果你是编译安装,而想卸载时又搞丢了当时的Makefile文件,那就比较讨厌了。有方法可以制作类似于Winodws下的绿色软件包吗?

答案是肯定的。我们可以利用ldd来实现这样的功能。ldd会告诉我们对应二进制可执行程序所用到的共享库文件,我们要做的第一步是在已安装好完整应用的机器上把这些共享库文件拿到。第二步便可以在其他干净的机器上利用LD_LIBRARY_PATH指定运行软件时的动态库文件地址,运行对应的二进制程序。

这里我写了一个实现第一步的脚本:

1#!/bin/sh
2 
3if [ $# -ne 1 ]; then
4        echo "You should specify a dynamically executable file"
5        exit 1
6fi
7 
8if [ ! -x $1 ]; then
9        echo "You should specify a executable file"
10        exit 1;
11fi
12 
13path=$1
14 
15############# check file type #############
16result=$(ldd $path)
17 
18filter=$(file $path|grep dynamically|grep executable)
19 
20if [ -z "$filter" ]; then
21        echo "$path is not a dynamically executable file!"
22        file $path
23        exit 1
24fi
25 
26########### mkdir for .so files ############
27packagename=$(basename $path)-pack
28mkdir -p $packagename
29 
30IFS="
31"
32 
33######### copy .so files ############
34for line in $result; do
35        sofile=notexitsfile
36        if [ -z "$(echo $line | grep =)" ]; then
37                sofile=$(echo $line | awk '{print $1}')
38        else
39                # has soft link
40                sofile=$(echo $line | awk '{print $3}')
41        fi
42 
43        if [ ! -f $sofile ]; then
44                echo "ERROR FILE: $sofile"
45        else
46                echo "copying $sofile now..."
47                cp $sofile $packagename
48        fi
49done
50 
51cp $path $packagename
52 
53echo DONE

这个脚本的接收二进制可执行程序的路径作为参数,利用ldd找到对应的so位置,并将它们连同二进制可执行程序本身拷贝到一个文件夹中。脚本正确执行完毕后,这个文件夹就可以拿到其他的干净的机器上运行了。

举个在CentOS5.3上的例子吧,例如我在A机器上已经编译安装(或者rpm 安装)好了ffmpeg。于是乎我就可以执行我的脚本fetchsofiles.sh,以/usr/bin/ffmpeg作为参数:

1[root@CT53-64-BASE ~]# ./fetchsofiles.sh /usr/bin/ffmpeg
2copying /usr/lib64/libpostproc.so.51 now...
3copying /usr/lib64/libswscale.so.0 now...
4copying /usr/lib/libavdevice.so.52 now...
5copying /usr/lib/libavformat.so.52 now...
6copying /usr/lib/libavcodec.so.52 now...
7copying /usr/lib/libavutil.so.49 now...
8copying /lib64/libm.so.6 now...
9copying /lib64/libpthread.so.0 now...
10copying /lib64/libc.so.6 now...
11copying /usr/lib64/libz.so.1 now...
12copying /lib64/libdl.so.2 now...
13copying /lib64/ld-linux-x86-64.so.2 now...
14DONE

看来是正确执行了,现在当前目录的ffmpeg-pack下就有了:

1[root@CT53-64-BASE ~]# ls -lh ffmpeg-pack/
2total 24M
3-rwx------ 1 root root  85K Jun  7 05:52 ffmpeg
4-rwx------ 1 root root 137K Jun  7 05:52 ld-linux-x86-64.so.2
5-rwx------ 1 root root 506K May 19 09:17 libamrnb.so.3
6-rwx------ 1 root root 392K May 19 09:17 libamrwb.so.3
7-rwx------ 1 root root 887K May 19 09:17 libasound.so.2
8-rwx------ 1 root root 4.5M Jun  7 05:52 libavcodec.so.52
9-rwx------ 1 root root  25K Jun  7 05:52 libavdevice.so.52
10-rwx------ 1 root root 647K Jun  7 05:52 libavformat.so.52
11-rwx------ 1 root root  45K Jun  7 05:52 libavutil.so.49
12-rwx------ 1 root root  67K May 19 09:17 libbz2.so.1
13-rwx------ 1 root root 1.7M Jun  7 05:52 libc.so.6<strong></strong>
14-rwx------ 1 root root 3.2M May 19 09:17 libdirac_decoder.so.0
15-rwx------ 1 root root 4.5M May 19 09:17 libdirac_encoder.so.0
16-rwx------ 1 root root  23K Jun  7 05:52 libdl.so.2
17-rwx------ 1 root root 232K May 19 09:17 libfaac.so.0
18-rwx------ 1 root root 729K May 19 09:17 libfaad.so.2
19-rwx------ 1 root root  58K May 19 09:17 libgcc_s.so.1
20-rwx------ 1 root root 955K May 19 09:17 libmp3lame.so.0
21-rwx------ 1 root root 601K Jun  7 05:52 libm.so.6
22-rwx------ 1 root root  22K May 19 09:17 libogg.so.0
23-rwx------ 1 root root  51K Jun  7 05:52 libpostproc.so.51
24-rwx------ 1 root root 143K Jun  7 05:52 libpthread.so.0
25-rwx------ 1 root root  53K May 19 09:17 librt.so.1
26-rwx------ 1 root root 954K May 19 09:17 libstdc++.so.6
27-rwx------ 1 root root 161K Jun  7 05:52 libswscale.so.0
28-rwx------ 1 root root 208K May 19 09:17 libtheora.so.0
29-rwx------ 1 root root 1.1M May 19 09:17 libX11.so.6
30-rwx------ 1 root root 1.8M May 19 09:17 libx264.so.68
31-rwx------ 1 root root  12K May 19 09:17 libXau.so.6
32-rwx------ 1 root root  22K May 19 09:17 libXdmcp.so.6
33-rwx------ 1 root root  71K May 19 09:17 libXext.so.6
34-rwx------ 1 root root  84K Jun  7 05:52 libz.so.1

24M,确实不小。我们现在就可以把这个24M的文件夹随处(*注1)拷贝了,例如我们现在将其拷贝到从来没有安装过ffmpeg及其相关依赖的机器B上,运行LD_LIBRARY_PATH=/your_pack_path /your_pack_path/ffmpeg:

1[root@CT53-64-BASE ~]# cd ffmpeg-pack/
2[root@CT53-64-BASE ffmpeg-pack]# LD_LIBRARY_PATH=. ./ffmpeg
3FFmpeg version 0.5, Copyright (c) 2000-2009 Fabrice Bellard, et al.
4  configuration: --prefix=/usr --libdir=/usr/lib64 --shlibdir=/usr/lib64 --mandir=/usr/share/man --incdir=/usr/include --extra-cflags=-fPIC --enable-libamr-nb --enable-libamr-wb --enable-libdirac --enable-libfaac --enable-libfaad --enable-libmp3lame --enable-libtheora --enable-libx264 --enable-gpl --enable-nonfree --enable-postproc --enable-pthreads --enable-shared --enable-swscale --enable-x11grab
5  libavutil     49.15. 0 / 49.15. 0
6  libavcodec    52.20. 0 / 52.20. 1
7  libavformat   52.31. 0 / 52.31. 0
8  libavdevice   52. 1. 0 / 52. 1. 0
9  libswscale     0. 7. 1 /  0. 7. 1
10  libpostproc   51. 2. 0 / 51. 2. 0
11  built on Nov  6 2009 19:11:04, gcc: 4.1.2 20080704 (Red Hat 4.1.2-46)
12At least one output file must be specified

很幸运,运行成功了!

  • 注1:所谓随处,并非任意的随处。必须是相同架构(arch),相同内核版本的机器之间才行。因为注意到这些被拷贝的so有的是架构相关,有的直接就是内核自己的so。

0 0
原创粉丝点击