ldd命令用于显示可执行文件或共享库依赖的动态链接库,直接运行
ldd 文件名
即可列出其所需的共享库及其路径。
想知道一个程序运行起来需要哪些“帮手”吗?在 Linux 和类 Unix 系统里,ldd
(List Dynamic Dependencies)命令就是你的得力助手,它能清晰地列出一个可执行程序或共享库所依赖的所有动态链接库(.so
文件),这对于排查程序无法启动(比如报错找不到某个 .so
文件)、理解程序结构、或者部署软件到新环境时确保所有依赖都到位,都非常有用。
最基本的用法就是直接在终端输入 ldd
,后面跟上你想检查的程序或库的完整路径:
ldd /path/to/your/program_or_library
举个最常见的例子:
你想看看系统自带的 ls
命令依赖哪些库:
ldd /bin/ls
执行后,你会看到类似这样的输出(具体库和路径会因系统和版本而异):
linux-vdso.so.1 (0x00007ffd5a3f1000) libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f9e3a6b8000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9e3a4c6000) libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007f9e3a42d000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f9e3a427000) /lib64/ld-linux-x86-64.so.2 (0x00007f9e3a70d000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f9e3a405000)
解读输出结果:
- 第一列: 依赖的共享库名称(
libc.so.6
)。 =>
: 表示该库被解析到的实际路径。- 第二列: 该库在系统上被找到的完整绝对路径(
/lib/x86_64-linux-gnu/libc.so.6
),这是最关键的信息!如果程序启动报错说找不到某个库,ldd
输出中对应的这一项通常会是not found
。 - 括号内的地址: 库被加载到内存中的地址(每次运行可能不同,一般用户无需深究)。
- 特殊项:
linux-vdso.so.1
: 一个虚拟库,用于加速系统调用,通常无需关心。/lib64/ld-linux-x86-64.so.2
: 这是动态链接器/加载器本身,负责在程序启动时加载所有依赖库,对于 64 位 x86 系统通常是这个路径,32 位系统可能是/lib/ld-linux.so.2
。
ldd
的常用选项:
虽然 ldd
本身选项不多,但有几个比较实用:
-
-v
或--verbose
: 详细模式
打印所有依赖信息,包括库的版本号、符号表信息等,输出非常详尽,对于深度调试很有用。ldd -v /bin/ls
-
-u
或--unused
: 显示未使用的直接依赖
尝试列出那些被链接进来但实际上没有被程序使用的直接依赖项,注意:这个结果可能不完全准确,仅供参考。ldd -u /bin/ls
-
-d
或--data-relocs
: 执行重定位并报告丢失的函数 (仅对 ELF 格式有效)
更严格地检查数据对象的重定位问题。 -
-r
或--function-relocs
: 执行重定位并报告丢失的函数和数据对象 (仅对 ELF 格式有效)
最严格的检查模式,会尝试执行重定位操作,报告任何找不到的函数或数据对象,这对于检查库的兼容性问题(比如某个依赖库版本太旧缺少需要的函数)很有帮助。ldd -r /path/to/program
ldd
使用场景与技巧:
-
诊断“找不到库”错误:
这是ldd
最核心的用途,如果运行程序时出现类似error while loading shared libraries: libxxx.so.x: cannot open shared object file: No such file or directory
的错误,立即用ldd
检查该程序:ldd /path/to/failing_program
在输出中查找标记为
not found
的库,这明确告诉你缺失了哪个库文件,接下来你需要:- 确认这个库是否已安装(用包管理器搜索,如
apt search libxxx
/dnf search libxxx
/yum search libxxx
/pacman -Ss libxxx
)。 - 如果已安装,检查路径是否在动态链接器的搜索范围内(通常由
/etc/ld.so.conf
和/etc/ld.so.conf.d/*
定义,以及环境变量LD_LIBRARY_PATH
),库文件通常安装在/lib
,/lib64
,/usr/lib
,/usr/lib64
,/usr/local/lib
等标准目录下。 - 如果库已安装但不在标准路径,可以通过设置
LD_LIBRARY_PATH
临时指定(不推荐长期使用),或者将库路径添加到/etc/ld.so.conf.d/
下的一个.conf
文件中,然后运行sudo ldconfig
更新缓存。
- 确认这个库是否已安装(用包管理器搜索,如
-
检查程序是否链接了特定库:
你可以结合grep
快速检查程序是否依赖了某个特定的库:ldd /path/to/program | grep libssl
如果有输出,说明依赖了 OpenSSL 库;没有输出则说明没有直接依赖。
-
查看库的依赖关系:
ldd
不仅可以检查可执行文件,也可以检查共享库文件 (.so
) 本身依赖哪些其他库:ldd /usr/lib/x86_64-linux-gnu/libssl.so.3
-
对比不同环境下的依赖:
在将程序部署到新服务器前,可以在开发机上用ldd
检查依赖,确保目标服务器上安装了所有必要的库(版本兼容性也需注意)。
重要警告与注意事项:
-
绝对不要对不受信任的程序使用
ldd
!
这是ldd
使用中最重要的安全准则。ldd
的工作原理是通过设置特殊的环境变量(如LD_TRACE_LOADED_OBJECTS
)来让动态链接器输出依赖信息,而不是直接运行程序。在极少数情况下,某些精心构造的恶意程序可能会利用这个机制,在ldd
试图“模拟”加载过程时执行其代码。 永远不要对来源不明、不可信的可执行文件运行ldd
,安全的做法是只对系统自带程序、你信任的软件包安装的程序或你自己编译的程序使用ldd
。 -
ldd
vsreadelf -d
:
另一个查看动态依赖的工具是readelf -d /path/to/program | grep NEEDED
,它直接从 ELF 文件头中读取.dynamic
段的信息,列出直接依赖的库名(但不解析路径)。ldd
会递归地列出所有依赖(直接和间接)并解析出它们在当前系统中的完整路径,两者用途略有不同:readelf -d
更安全(因为它不涉及任何加载或执行),适合快速查看直接依赖;ldd
更全面,能显示实际加载路径,但需注意安全风险。 -
版本兼容性:
ldd
显示的是库在当前系统上的路径和版本,这并不意味着程序在运行时一定能和这个版本的库完美协作(可能存在 ABI 不兼容)。ldd -r
可以帮助发现一些符号缺失的问题。 -
环境变量影响:
ldd
的输出会受到环境变量(尤其是LD_LIBRARY_PATH
)的影响,同一个程序在不同LD_LIBRARY_PATH
设置下运行ldd
,可能会找到不同路径下的库。
ldd
是一个简单而强大的命令行工具,是 Linux 用户和开发者诊断程序依赖问题、理解程序构成的必备利器,记住它的核心功能:列出可执行文件或共享库所需的动态链接库及其在系统中的实际路径,熟练掌握 ldd
的基础用法和常用选项(-v
, -u
, -r
),能有效解决常见的“库未找到”错误,但务必牢记安全第一的原则:切勿对不可信的程序使用 ldd
,对于快速查看直接依赖,安全的替代方案是 readelf -d | grep NEEDED
,善用 ldd
,让你的 Linux 程序运行和调试更加得心应手。
引用说明:
ldd
的功能描述和选项解释主要基于 GNU C 库 (glibc
) 中ldd
实现的通用行为以及 Linux 手册页 (man ldd
) 的标准内容。ldd
安全风险的警告广泛存在于 Linux 社区的安全建议和官方文档(如man ldd
中通常包含相关警告提示)。
原创文章,发布者:酷番叔,转转请注明出处:https://cloud.kd.cn/ask/6188.html