部署前先验二进制
把本机编译的程序或第三方二进制拿到目标机上跑不起来,最常见的两类原因是架构不匹配(在 x86_64 上跑 aarch64 的程序)与动态库缺失。部署前用三条命令就能排掉大部分问题:file 看架构与链接方式,ldd 看依赖库能否解析,readelf 读 ELF 头确认位宽与机器类型。架构对了、缺库清零,再启动才有意义。
基本信息
| 看架构与类型 | file 二进制、file 动态库 |
|---|---|
| 看依赖解析 | ldd 二进制(输出含 not found 即缺库) |
| 看 ELF 头 | readelf -h(Class 位宽、Machine 架构、Type 类型) |
| 看符号依赖 | readelf -d、objdump -p |
| 缺库定位 | dnf provides 'libxxx.so.N'、rpm -qf 库文件路径 |
| 自定义库路径 | LD_LIBRARY_PATH 或 /etc/ld.so.conf.d/ + ldconfig |
典型使用场景
- 迁移时将 x86_64 编译的二进制搬到 aarch64 服务器前先验证
- 第三方商业软件部署前确认依赖库是否齐全
- 服务启动报加载共享库失败时定位缺失依赖
- 交接时核对程序与运行环境的兼容关系
- 自建编译产物打包前检查依赖,避免带环境不匹配的包
检查三件套
检查三件套
file /opt/app/bin/app # 显示架构(x86-64/aarch64)与动态链接信息
file /opt/app/lib/*.so | head # 动态库也要分别确认架构一致
ldd /opt/app/bin/app # 依赖库解析结果
ldd /opt/app/bin/app | grep 'not found' # 关键检查:缺库清单必须为零
readelf -h /opt/app/bin/app | head # ELF 头:Class、Machine、Type
readelf -d /opt/app/bin/app | head -20 # 动态段:依赖的库名与 RPATH/RUNPATH缺库处理
缺库处理
# 按缺失库名反查软件包(示例):
dnf provides 'libssl.so.1.1' 2>/dev/null | head
# 或确认库位于自定义路径:
LD_LIBRARY_PATH=/opt/app/lib ldd /opt/app/bin/app | grep 'not found' || echo OK
# 需要长期生效时登记库路径:
echo /opt/app/lib > /etc/ld.so.conf.d/app.conf && ldconfig
df -h / ; ls -l /opt/app/lib | head # 顺带确认磁盘与库文件存在性输出逐项读法
| 输出 | 含义 | 判读要点 |
|---|---|---|
| file 的 ELF 64-bit LSB executable, x86-64 | 架构与位宽 | 与目标机 uname -m 不一致即无法运行 |
| file 的 aarch64 | ARM64 架构 | 需要同架构机器或交叉编译产物 |
| dynamically linked | 动态链接 | 需检查依赖库;静态链接则无外部依赖 |
| ldd 的 not found | 依赖库缺失 | 逐条归零后再启动 |
| ldd 的路径指向 | 库的实际来源路径 | 指向非预期路径时排查 LD_LIBRARY_PATH |
| readelf 的 Machine | ELF 头中的机器类型 | 与 uname -m 交叉验证 |
不要对来源不明的二进制直接执行 ldd:历史上存在借动态加载器执行代码的利用方式,先在隔离环境或不可执行的安全目录中检查。
ldd 的结果依赖当前环境的库搜索路径:同一份二进制在编译机与目标机上输出可能不同,验证必须在目标机上进行,缺库项逐条清零再启动。