为什么编译安装了 OpenSSL 1.1.1,openssl version 还是显示 1.0.2

举报
yd_224417480 发表于 2026/10/26 09:14:19 2026/10/26
【摘要】 摘要:从源码编译安装 OpenSSL 是最常见的运维操作之一,但装完执行 openssl version 依然显示系统自带的 1.0.2k,或者干脆报 error while loading shared libraries: libssl.so.1.1。这不是编译失败,而是系统里同时存在两套 OpenSSL,而 shell 找错了那一套。这篇文章把三个查找层次(命令、动态库、引擎插件)拆开...

摘要:从源码编译安装 OpenSSL 是最常见的运维操作之一,但装完执行 openssl version 依然显示系统自带的 1.0.2k,或者干脆报 error while loading shared libraries: libssl.so.1.1。这不是编译失败,而是系统里同时存在两套 OpenSSL,而 shell 找错了那一套。这篇文章把三个查找层次(命令、动态库、引擎插件)拆开讲清楚。

一、现象:装完了,版本没变

在 CentOS 7.6 上按标准流程编译安装:

cd /home && tar -xzf openssl-OpenSSL_1_1_1a.tar.gz
cd openssl-OpenSSL_1_1_1a
./config --prefix=/usr/local --openssldir=/usr/local/ssl shared
make -j4 && make install

make install 结束,/usr/local/bin/openssl 确实存在,但:

$ openssl version
OpenSSL 1.0.2k-fips  26 Jan 2017      # 还是老的

$ /usr/local/bin/openssl version
/usr/local/bin/openssl: error while loading shared libraries: libssl.so.1.1: cannot open shared object file

先别怀疑编译。error while loading shared libraries 是动态链接器在加载阶段就失败了,和 OpenSSL 自身逻辑无关;而第一条命令跑的是另一个二进制文件。两个现象对应的是两个不同层次的问题。

二、层次一:命令查找顺序(PATH)

openssl 到底跑的是哪一个?用 which -a 而不是 which:

$ which -a openssl
/usr/bin/openssl
/usr/local/bin/openssl

which 只告诉你第一个,-a 才把所有候选列出来。CentOS 的 /etc/profile 默认把 /usr/local/bin 放在 PATH 里,但位置在 /usr/bin 之后——因为 /usr/local/bin 是追加的。所以哪怕装好了,敲 openssl 仍旧命中 /usr/bin/openssl。

正确的做法是把 /usr/local/bin 前置:

echo 'export PATH=/usr/local/bin:$PATH' >> /etc/profile
source /etc/profile

注意 $PATH 放在后面(前置),而不是 export PATH=$PATH:/usr/local/bin。顺序就是优先级。

还有一个容易被忽略的坑:bash 会缓存命令路径。改完 PATH 后如果当前会话里已经执行过 openssl,shell 的 hash 表里还记着旧路径,需要 hash -r 清缓存(新开会话则无此问题)。

三、层次二:动态库搜索路径(ld.so.conf)

命令找对了,第二层问题就冒出来了:新二进制依赖 libssl.so.1.1、libcrypto.so.1.1,而它们被 make install 放到了 /usr/local/lib(或 /usr/local/lib64)。动态链接器 ld.so 默认只搜 /lib、/usr/lib、/lib64、/usr/lib64,不包含 /usr/local/lib,于是报找不到。

LD_LIBRARY_PATH 能临时解决,但它不持久、且对所有子进程生效,高并发服务里容易变成隐患。标准做法是登记到 ld.so.conf 再刷新缓存:

echo "/usr/local/lib/" >> /etc/ld.so.conf
ldconfig

ldconfig 会重建 /etc/ld.so.cache,之后加载器就能找到新库。验证:

ldconfig -p | grep -E 'libssl|libcrypto'

应当能看到 libssl.so.1.1 指向 /usr/local/lib。

为什么系统库不冲突:libssl.so.1.0.2k 和 libssl.so.1.1 的 SONAME 不同,可以并存;/usr/bin/openssl 继续用它自己的 1.0.2,/usr/local/bin/openssl 用 1.1.1,互不干扰。这也是为什么「装新版」通常不需要先卸载旧版——但反过来,两套并存意味着你必须确认每条命令跑的是哪一套。

四、层次三:引擎插件搜索路径(OPENSSL_ENGINES)

如果还用到硬件加速引擎(例如鲲鹏的 KAE、Intel 的 QAT),那还有第三个查找层:OpenSSL 的 engine 插件目录。

$ openssl engine -t -c kae
(kae) Kunpeng Accelerator Engine
 [RSA, DH, rsaEncryption, dhKeyAgreement, dhpublicnumber]
     [ available ]

当 engine 报 unable to load engine 或者列表里根本没有它时,多半是没告诉 OpenSSL 插件在哪:

export OPENSSL_ENGINES=/usr/local/lib/engines-1.1

或者写进 /etc/profile 持久化。engine 还可以通过 openssl.cnf 里的 dynamic_path 显式指定 .so 的绝对路径,这种方式比环境变量更可控,适合放进配置文件而不是依赖全局变量。

顺带说一句:engine -t 显示 [ available ] 只代表用户态插件加载成功,不代表硬件真的在干活。硬件加速还需要内核态驱动(比如 hisi_hpre 这类模块)已经加载,lsmod 里看不到、/sys/class/uacce 不存在时,engine 依然是「可用但空转」——性能测试数字会和纯软件一模一样。这一点在排查「明明开了加速却没提速」时特别容易踩。

五、一分钟自检清单

装完 OpenSSL 之后,按顺序跑这五条,基本能覆盖 90% 的「版本没生效」问题:

which -a openssl                          # 跑的是哪一个
/usr/local/bin/openssl version            # 新二进制能否单独启动
ldd /usr/local/bin/openssl | grep -E 'ssl|crypto'   # 动态库解析到哪
ldconfig -p | grep libssl                 # 缓存里有没有 1.1
echo $OPENSSL_CONF $OPENSSL_ENGINES       # 配置文件与插件路径

六、小结

「装了没生效」几乎从来不是编译或安装失败,而是查找顺序问题:命令走 PATH,库走 ld.so.cache,引擎走 OPENSSL_ENGINES。三者都不做处理时,系统会安静地继续用旧的那一套——命令能跑、版本没变、报错也不明显。

理解了这三层,以后再遇到 libxxx.so not found、command not found、engine not found,排查顺序就是固定的:先确认跑的是哪个文件,再确认它依赖的库在哪,最后确认插件/配置路径对不对。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。