ubuntu批量依赖库拷贝(ldd)

背景

如何将程序依赖的动态库拷贝到指定的目录?

例子

  1. 通过LDD查看依赖的动态库。
$ ldd extract_gpu
        linux-vdso.so.1 (0x00007ffd931e4000)
        libopencv_cudacodec.so.4.1 => /home/joyner/disk1/mmaction/third_party/opencv-4.1.0/build/lib/libopencv_cudacodec.so.4.1 (0x00007f064e89f000)
        libopencv_cudaoptflow.so.4.1 => /home/joyner/disk1/mmaction/third_party/opencv-4.1.0/build/lib/libopencv_cudaoptflow.so.4.1 (0x00007f064c710000)
        libopencv_videoio.so.4.1 => /home/joyner/disk1/mmaction/third_party/opencv-4.1.0/build/lib/libopencv_videoio.so.4.1 (0x00007f064c4b8000)
        libopencv_imgcodecs.so.4.1 => /home/joyner/disk1/mmaction/third_party/opencv-4.1.0/build/lib/libopencv_imgcodecs.so.4.1 (0x00007f064baf5000)
        libopencv_imgproc.so.4.1 => /home/joyner/disk1/mmaction/third_party/opencv-4.1.0/build/lib/libopencv_imgproc.so.4.1 (0x00007f0649205000)
        libopencv_cudaarithm.so.4.1 => /home/joyner/disk1/mmaction/third_party/opencv-4.1.0/build/lib/libopencv_cudaarithm.so.4.1 (0x00007f063d75c000)
        libopencv_core.so.4.1 => /home/joyner/disk1/mmaction/third_party/opencv-4.1.0/build/lib/libopencv_core.so.4.1 (0x00007f063bac0000)
        libzip.so.4 => /usr/lib/x86_64-linux-gnu/libzip.so.4 (0x00007f063b8ac000)
        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f063b523000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f063b30b000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f063af1a000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f063acfb000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f063aaf7000)
        librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f063a8ef000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f064eded000)
        libopencv_cudawarping.so.4.1 => /home/joyner/disk1/mmaction/third_party/opencv-4.1.0/build/lib/libopencv_cudawarping.so.4.1 (0x00007f0636519000)
        libopencv_cudalegacy.so.4.1 => /home/joyner/disk1/mmaction/third_party/opencv-4.1.0/build/lib/libopencv_cudalegacy.so.4.1 (0x00007f063550e000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f0635170000)
        libdc1394.so.22 => /usr/lib/x86_64-linux-gnu/libdc1394.so.22 (0x00007f0634efa000)
        libgstreamer-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libgstreamer-1.0.so.0 (0x00007f0634bbf000)
        libgobject-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0 (0x00007f063496b000)
        libglib-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x00007f0634654000)
        libgstapp-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libgstapp-1.0.so.0 (0x00007f0634445000)
        libgstriff-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libgstriff-1.0.so.0 (0x00007f0634237000)
        libgstpbutils-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libgstpbutils-1.0.so.0 (0x00007f0633fff000)
        libavcodec.so.58 => /usr/local/lib/libavcodec.so.58 (0x00007f063295a000)
        libavformat.so.58 => /usr/local/lib/libavformat.so.58 (0x00007f063250a000)
        libavutil.so.56 => /usr/local/lib/libavutil.so.56 (0x00007f0632294000)
        libswscale.so.5 => /usr/local/lib/libswscale.so.5 (0x00007f0632009000)
        libjpeg.so.8 => /usr/lib/x86_64-linux-gnu/libjpeg.so.8 (0x00007f0631da1000)
        libpng16.so.16 => /usr/lib/x86_64-linux-gnu/libpng16.so.16 (0x00007f0631b6f000)
        libtiff.so.5 => /usr/lib/x86_64-linux-gnu/libtiff.so.5 (0x00007f06318f8000)
        libjasper.so.1 => /usr/lib/x86_64-linux-gnu/libjasper.so.1 (0x00007f06316a3000)
        libz.so.1 => /usr/local/lib/libz.so.1 (0x00007f0631487000)
        libnppc.so.10 => /usr/local/cuda/lib64/libnppc.so.10 (0x00007f063120c000)
        libnppial.so.10 => /usr/local/cuda/lib64/libnppial.so.10 (0x00007f06304bd000)
        libnppidei.so.10 => /usr/local/cuda/lib64/libnppidei.so.10 (0x00007f062fad0000)
        libnppig.so.10 => /usr/local/cuda/lib64/libnppig.so.10 (0x00007f062e00a000)
        libnppist.so.10 => /usr/local/cuda/lib64/libnppist.so.10 (0x00007f062cc5e000)
        libnppitc.so.10 => /usr/local/cuda/lib64/libnppitc.so.10 (0x00007f062c775000)
        libcublas.so.10 => /usr/lib/x86_64-linux-gnu/libcublas.so.10 (0x00007f06284bf000)
        libcufft.so.10 => /usr/local/cuda/lib64/libcufft.so.10 (0x00007f062130a000)
        libtbb.so.2 => /usr/lib/x86_64-linux-gnu/libtbb.so.2 (0x00007f06210ce000)
        libopencv_cudaimgproc.so.4.1 => /home/joyner/disk1/mmaction/third_party/opencv-4.1.0/build/lib/libopencv_cudaimgproc.so.4.1 (0x00007f061e7ac000)
        libopencv_objdetect.so.4.1 => /home/joyner/disk1/mmaction/third_party/opencv-4.1.0/build/lib/libopencv_objdetect.so.4.1 (0x00007f061e546000)
        libopencv_cudafilters.so.4.1 => /home/joyner/disk1/mmaction/third_party/opencv-4.1.0/build/lib/libopencv_cudafilters.so.4.1 (0x00007f0601d18000)
        libopencv_calib3d.so.4.1 => /home/joyner/disk1/mmaction/third_party/opencv-4.1.0/build/lib/libopencv_calib3d.so.4.1 (0x00007f060197b000)
        libraw1394.so.11 => /usr/lib/x86_64-linux-gnu/libraw1394.so.11 (0x00007f060176c000)
        libusb-1.0.so.0 => /lib/x86_64-linux-gnu/libusb-1.0.so.0 (0x00007f0601554000)
        libgmodule-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.0 (0x00007f0601350000)
        libffi.so.6 => /usr/lib/x86_64-linux-gnu/libffi.so.6 (0x00007f0601148000)
        libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f0600ed6000)
        libgstbase-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libgstbase-1.0.so.0 (0x00007f0600c61000)
        libgstaudio-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libgstaudio-1.0.so.0 (0x00007f06009ec000)
        libgsttag-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libgsttag-1.0.so.0 (0x00007f06007b1000)
        libgstvideo-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libgstvideo-1.0.so.0 (0x00007f0600518000)
        libswresample.so.3 => /usr/local/lib/libswresample.so.3 (0x00007f06002fb000)
        liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007f06000d5000)
        libjbig.so.0 => /usr/lib/x86_64-linux-gnu/libjbig.so.0 (0x00007f05ffec7000)
        libcublasLt.so.10 => /usr/lib/x86_64-linux-gnu/libcublasLt.so.10 (0x00007f05fe034000)
        libnppicc.so.10 => /usr/local/cuda/lib64/libnppicc.so.10 (0x00007f05fda56000)
        libnpps.so.10 => /usr/local/cuda/lib64/libnpps.so.10 (0x00007f05fcfd3000)
        libnppif.so.10 => /usr/local/cuda/lib64/libnppif.so.10 (0x00007f05fa099000)
        libnppim.so.10 => /usr/local/cuda/lib64/libnppim.so.10 (0x00007f05f989a000)
        libopencv_features2d.so.4.1 => /home/joyner/disk1/mmaction/third_party/opencv-4.1.0/build/lib/libopencv_features2d.so.4.1 (0x00007f05f95c7000)
        libopencv_flann.so.4.1 => /home/joyner/disk1/mmaction/third_party/opencv-4.1.0/build/lib/libopencv_flann.so.4.1 (0x00007f05f936e000)
        libudev.so.1 => /lib/x86_64-linux-gnu/libudev.so.1 (0x00007f05f9150000)
        liborc-0.4.so.0 => /usr/lib/x86_64-linux-gnu/liborc-0.4.so.0 (0x00007f05f8ed4000)
  1. 写一个SHELL脚本,自动拷贝依赖的动态库。

vi release.sh

#!/bin/bash
deplist=$( ldd $1 | awk '{if (match($3,"/")){ print $3}}' )  
cp -L -n $deplist $2 
-L 表示拷贝文件(如果是软链,会拷贝到最终的文件)。 
-n 表示不覆盖已有文件。 
  1. 创建目标目录
mkdir release
  1. 将postgres依赖的动态库拷贝到目标目录
bash release.sh extract_gpu ./release/  
ll ./release

total 1.3G
drwxrwxr-x 2 joyner joyner 4.0K 6月   8 15:33 .
drwxrwxr-x 4 joyner joyner 4.0K 6月   8 15:33 ..
-rwxr-xr-x 1 joyner joyner  13M 6月   8 15:33 libavcodec.so.58
-rwxr-xr-x 1 joyner joyner 2.4M 6月   8 15:33 libavformat.so.58
-rwxr-xr-x 1 joyner joyner 411K 6月   8 15:33 libavutil.so.56
-rwxr-xr-x 1 joyner joyner 2.0M 6月   8 15:33 libc.so.6
-rwxr-xr-x 1 joyner joyner  29M 6月   8 15:33 libcublasLt.so.10
-rwxr-xr-x 1 joyner joyner  65M 6月   8 15:33 libcublas.so.10
-rwxr-xr-x 1 joyner joyner 112M 6月   8 15:33 libcufft.so.10
-rw-r--r-- 1 joyner joyner 216K 6月   8 15:33 libdc1394.so.22
-rw-r--r-- 1 joyner joyner  15K 6月   8 15:33 libdl.so.2
-rw-r--r-- 1 joyner joyner  31K 6月   8 15:33 libffi.so.6
-rw-r--r-- 1 joyner joyner  95K 6月   8 15:33 libgcc_s.so.1
-rw-r--r-- 1 joyner joyner 1.1M 6月   8 15:33 libglib-2.0.so.0
-rw-r--r-- 1 joyner joyner  14K 6月   8 15:33 libgmodule-2.0.so.0
-rw-r--r-- 1 joyner joyner 335K 6月   8 15:33 libgobject-2.0.so.0
-rw-r--r-- 1 joyner joyner  60K 6月   8 15:33 libgstapp-1.0.so.0
-rw-r--r-- 1 joyner joyner 466K 6月   8 15:33 libgstaudio-1.0.so.0
-rw-r--r-- 1 joyner joyner 469K 6月   8 15:33 libgstbase-1.0.so.0
-rw-r--r-- 1 joyner joyner 226K 6月   8 15:33 libgstpbutils-1.0.so.0
-rw-r--r-- 1 joyner joyner 1.3M 6月   8 15:33 libgstreamer-1.0.so.0
-rw-r--r-- 1 joyner joyner  55K 6月   8 15:33 libgstriff-1.0.so.0
-rw-r--r-- 1 joyner joyner 237K 6月   8 15:33 libgsttag-1.0.so.0
-rw-r--r-- 1 joyner joyner 610K 6月   8 15:33 libgstvideo-1.0.so.0
-rw-r--r-- 1 joyner joyner 311K 6月   8 15:33 libjasper.so.1
-rw-r--r-- 1 joyner joyner  57K 6月   8 15:33 libjbig.so.0
-rw-r--r-- 1 joyner joyner 415K 6月   8 15:33 libjpeg.so.8
-rw-r--r-- 1 joyner joyner 151K 6月   8 15:33 liblzma.so.5
-rw-r--r-- 1 joyner joyner 1.7M 6月   8 15:33 libm.so.6
-rwxr-xr-x 1 joyner joyner 486K 6月   8 15:33 libnppc.so.10
-rwxr-xr-x 1 joyner joyner  12M 6月   8 15:33 libnppial.so.10
-rwxr-xr-x 1 joyner joyner 3.9M 6月   8 15:33 libnppicc.so.10
-rwxr-xr-x 1 joyner joyner 7.8M 6月   8 15:33 libnppidei.so.10
-rwxr-xr-x 1 joyner joyner  46M 6月   8 15:33 libnppif.so.10
-rwxr-xr-x 1 joyner joyner  25M 6月   8 15:33 libnppig.so.10
-rwxr-xr-x 1 joyner joyner 6.0M 6月   8 15:33 libnppim.so.10
-rwxr-xr-x 1 joyner joyner  18M 6月   8 15:33 libnppist.so.10
-rwxr-xr-x 1 joyner joyner 3.0M 6月   8 15:33 libnppitc.so.10
-rwxr-xr-x 1 joyner joyner 8.4M 6月   8 15:33 libnpps.so.10
-rwxrwxr-x 1 joyner joyner 1.8M 6月   8 15:33 libopencv_calib3d.so.4.1
-rwxrwxr-x 1 joyner joyner  29M 6月   8 15:33 libopencv_core.so.4.1
-rwxrwxr-x 1 joyner joyner 186M 6月   8 15:33 libopencv_cudaarithm.so.4.1
-rwxrwxr-x 1 joyner joyner 810K 6月   8 15:33 libopencv_cudacodec.so.4.1
-rwxrwxr-x 1 joyner joyner 458M 6月   8 15:33 libopencv_cudafilters.so.4.1
-rwxrwxr-x 1 joyner joyner  40M 6月   8 15:33 libopencv_cudaimgproc.so.4.1
-rwxrwxr-x 1 joyner joyner  15M 6月   8 15:33 libopencv_cudalegacy.so.4.1
-rwxrwxr-x 1 joyner joyner  32M 6月   8 15:33 libopencv_cudaoptflow.so.4.1
-rwxrwxr-x 1 joyner joyner  67M 6月   8 15:33 libopencv_cudawarping.so.4.1
-rwxrwxr-x 1 joyner joyner 975K 6月   8 15:33 libopencv_features2d.so.4.1
-rwxrwxr-x 1 joyner joyner 460K 6月   8 15:33 libopencv_flann.so.4.1
-rwxrwxr-x 1 joyner joyner 8.4M 6月   8 15:33 libopencv_imgcodecs.so.4.1
-rwxrwxr-x 1 joyner joyner  41M 6月   8 15:33 libopencv_imgproc.so.4.1
-rwxrwxr-x 1 joyner joyner 491K 6月   8 15:33 libopencv_objdetect.so.4.1
-rwxrwxr-x 1 joyner joyner 415K 6月   8 15:33 libopencv_videoio.so.4.1
-rw-r--r-- 1 joyner joyner 497K 6月   8 15:33 liborc-0.4.so.0
-rw-r--r-- 1 joyner joyner 454K 6月   8 15:33 libpcre.so.3
-rw-r--r-- 1 joyner joyner 198K 6月   8 15:33 libpng16.so.16
-rwxr-xr-x 1 joyner joyner 142K 6月   8 15:33 libpthread.so.0
-rw-r--r-- 1 joyner joyner  59K 6月   8 15:33 libraw1394.so.11
-rw-r--r-- 1 joyner joyner  31K 6月   8 15:33 librt.so.1
-rw-r--r-- 1 joyner joyner 1.6M 6月   8 15:33 libstdc++.so.6
-rwxr-xr-x 1 joyner joyner 115K 6月   8 15:33 libswresample.so.3
-rwxr-xr-x 1 joyner joyner 523K 6月   8 15:33 libswscale.so.5
-rw-r--r-- 1 joyner joyner 230K 6月   8 15:33 libtbb.so.2
-rw-r--r-- 1 joyner joyner 475K 6月   8 15:33 libtiff.so.5
-rw-r--r-- 1 joyner joyner 119K 6月   8 15:33 libudev.so.1
-rw-r--r-- 1 joyner joyner  95K 6月   8 15:33 libusb-1.0.so.0
-rw-r--r-- 1 joyner joyner  79K 6月   8 15:33 libzip.so.4
-rwxr-xr-x 1 joyner joyner 120K 6月   8 15:33 libz.so.1
<think>好的,我需要解释一下ldd查找依赖库的原理。首先,我得回忆一下ldd的作用,它主要是用来显示一个可执行文件或者共享所依赖的动态链接。那用户想知道的是它的工作原理,对吧? 首先,我应该想到动态链接的基本概念。在Linux系统中,程序运行时需要动态链接器(比如ld-linux.so)来加载所需的共享ldd应该是利用了这个机制来获取依赖信息。但具体是怎么操作的呢? 接下来,可能需要了解ldd的实现方式。我记得ldd其实是一个脚本,它会设置一些环境变量,比如LD_TRACE_LOADED_OBJECTS,当这个变量被设置为1时,动态链接器就不会执行程序,而是输出依赖的。所以ldd可能通过设置这个环境变量,然后启动程序,让动态链接器输出信息。 不过,有些资料提到ldd实际上是通过调用动态链接器来完成的,例如执行类似于/lib/ld-linux.so.2 --list program这样的命令。这样的话,ldd其实是间接调用了动态链接器本身来列出依赖项。 另外,需要注意安全性的问题。因为ldd会实际加载程序的部分代码,所以可能存在风险,比如遇到恶意程序时,执行ldd可能会导致意外行为。这也是为什么有时候建议不要对不可信的可执行文件使用ldd,而是用objdump或者readelf来查看依赖。 然后,我需要考虑ldd的工作步骤。比如,首先解析可执行文件的ELF头,找到动态段(.dynamic section),其中包含了依赖的列表以及动态链接器的路径。然后,通过动态链接器来递归加载这些,并解析它们的依赖关系。但ldd并不真正运行程序,只是模拟加载过程来收集信息。 还有,ldd的输出可能包括直接依赖和间接依赖。直接依赖是ELF文件中明确列出的,而间接依赖则是这些所依赖的其他。动态链接器会处理这些递归依赖,而ldd通过环境变量触发这种跟踪模式。 可能还需要对比其他工具,比如objdump -p或者readelf -d,这些命令可以直接查看ELF文件的动态段,列出直接的依赖库,但不会递归显示所有间接依赖。而ldd则能显示完整的依赖链,因为它利用了动态链接器的功能。 另外,需要考虑不同系统上的差异,比如GLIBC和musl的动态链接器可能行为不同,但ldd的原理大体相似,都是通过触发动态链接器的跟踪模式。 总结一下,ldd的原理主要依赖于动态链接器的功能,通过设置环境变量或者直接调用动态链接器,使其在跟踪模式下输出依赖库信息,而不是实际运行程序。这个过程涉及ELF文件解析和动态链接器的协作。</think>ldd(List Dynamic Dependencies)是 Linux 系统中用于查询可执行文件或共享依赖关系的工具。其核心原理基于 **动态链接器的协作** 和 **ELF 文件解析**,以下是逐步说明: --- ### 1. **ELF 文件头解析** 当执行 `ldd` 命令时,首先会解析目标文件(如 `a.out`)的 **ELF 头**,定位到 `.dynamic` 段。该段记录了: - **直接依赖的列表**(如 `libc.so.6`) - **动态链接器路径**(如 `/lib/ld-linux-x86-64.so.2`) 通过 `readelf -d <文件>` 或 `objdump -p <文件>` 可直接查看这些信息。 --- ### 2. **触发动态链接器的跟踪模式** `ldd` 并非直接解析依赖,而是通过 **动态链接器(ld.so)** 的跟踪功能实现。具体分为两种方式: #### **方法一:环境变量控制** - 设置 `LD_TRACE_LOADED_OBJECTS=1`,使动态链接器进入跟踪模式。 - 执行命令时,动态链接器输出依赖信息而非运行程序: ```bash $ LD_TRACE_LOADED_OBJECTS=1 /lib/ld-linux-x86-64.so.2 ./a.out ``` #### **方法二:调用动态链接器** - 直接通过动态链接器加载目标文件,并传递 `--list` 参数: ```bash $ /lib/ld-linux-x86-64.so.2 --list ./a.out ``` `ldd` 本质是封装了上述操作(可通过 `strace ldd a.out` 观察系统调用验证)。 --- ### 3. **递归解析依赖关系** 动态链接器会按以下步骤递归加载所有依赖: 1. 读取目标文件的直接依赖库(如 `libA.so`)。 2. 加载 `libA.so` 并解析其 `.dynamic` 段,获取其依赖(如 `libB.so`)。 3. 重复过程,直到所有间接依赖被解析。 最终,`ldd` 输出完整的依赖树。 --- ### 4. **安全性风险** - **注意**:`ldd` 会触发动态链接器加载目标文件的部分代码,若文件为恶意程序,可能导致意外执行。建议对不可信文件改用: ```bash $ objdump -p <文件> | grep NEEDED # 仅查看直接依赖 ``` --- ### 对比其他工具 | 工具/命令 | 原理 | 特点 | |---------------------|--------------------------------|----------------------------------| | `ldd` | 调用动态链接器跟踪模式 | 显示完整依赖链,但有安全风险 | | `objdump -p` | 直接解析 ELF 文件的 `.dynamic` 段 | 仅显示直接依赖,无执行风险 | | `readelf -d` | 同上 | 类似 `objdump`,输出更详细 | --- ### 总结 - **核心原理**:通过动态链接器的跟踪功能输出依赖信息。 - **关键步骤**:解析 ELF 头 → 触发动态链接器 → 递归加载依赖。 - **替代方案**:对不可信文件使用 `objdump` 或 `readelf` 避免潜在风险。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值