每天进步一点点:Linux动态库搜索路径 & 有魔力的冒号(:)

Words
1167
Reading
6 min
Listen
Play
4y

还记得我将VPS从Ubuntu 18.04 LTS升级到Ubuntu 22.04 LTS导致cleos(EOS客户端)执行时找不到依赖库的问题嘛?

image.png
(图源 :pixabay)

我最终的解决方法是在Ubuntu 22.04 LTS下重新编译了EOS源码(确切地说是从新编译Leap),生产了新的cleos,一劳永逸地解决了问题。

不过今天运行另外一个项目的客户端时,发生了类似的问题,但是这个项目好久没有更新代码了,更是不支持在Ubuntu 22.04 LTS上编译,这可咋办?

设置动态库搜索路径

无论是重新编译项目还是降级系统都不太靠谱,那么就没办法了嘛?

其实在cleos找不到依赖库时,最初我使用的是一个折中的办法,那就是从其它主机上复制对应文件到相应的目录下,然后再执行软件。

首先用ldd查看软件的依赖:

ldd my_program

响应如下:

image.png

从中不难看出缺少libssl.so.1.0.0以及libcrypto.so.1.0.0,以往我的做法是从其它机器(运行18.04)或者网络上,找到这两个文件,然后复制到对应的目录,比如说: /lib/x86_64-linux-gnu/中。

但是这样做有两个问题:

  • 复制时需提供root权限(否则会提示Permission denied)
  • 让系统目录中有了本不该存在的内容,感觉系统被污染了

那么有没有办法,把这两个动态库直接放到软件对应的目录下,让软件执行的时候可以找到它们呢?这就要提到动态库搜索路径了。

我们可以通过以下两种方法修改动态库的搜索路径:

  • 编辑/etc/ld.so.conf,然后执行sudo ldconfig
  • 修改环境变量LD_LIBRARY_PATH来指定动态库的搜索路径

很明显,第一种方法仍然需要我们提供root权限,不予考虑。那么环境变量LD_LIBRARY_PATH如何设置呢?

答案也很简单,执行诸如如下指令就可以啦:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/your/path

其中/your/path就是my_program所在的目录,比如说/home/zhangsan。

需要说明的是,这种方式只对当前登录的会话有效,重新登录后,需要重新执行上述指令。如果要经常使用,那么推荐将上述指令写入.bashrc。

有魔力的冒号

通过设置 LD_LIBRARY_PATH,我们解决了软件找不到动态库的问题,但是这过程中我发现了一个有趣的事情。

回到上边提到的指令:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/zhangsan

这个指令很好理解,就是在原来的动态库搜索路径后,追加上自己的目录。其中:用来分隔不同的路径。

比如我们要程序搜索/aaa /bbb /ccc三个目录,那么这个变量最终的值,应该类似/aaa:/bbb:/ccc。

可是上述指令,我第一次执行时$LD_LIBRARY_PATH并没有被设置,所以最终$LD_LIBRARY_PATH的值为::/home/zhangsan。

虽然:看着怪怪的,但是似乎并不影响程序找到动态库。但是,真的就如此简单嘛?

我为了让程序所在目录更简洁,在相应账户下创建了一个lib目录,并将动态库复制进去一份,然后执行指令更新为:

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/zhangsan/lib

echo $LD_LIBRARY_PATH显示如下内容:

:/home/zhangsan/lib

可是我执行ldd时,发现链接的竟然是/home/zhangsan/下的动态库,而不是我期望的/home/zhangsan/lib:

1672650955923.png

如果我删除了/home/zhangsan下的动态库,则查找正常:

1672651102869.png

也就是说,程序先查找/home/zhangsan/再查找/home/zhangsan/bin目录,为什么会这样呢?我陷入了深深的思索当中,我觉得之所以这样,肯定和:有关。

最终终于在man bash中的PATH条目下找到答案,其中有这样一句话:

A zero-length (null) directory name in the value of PATH indicates the current directory. A null directory name may appear as two adjacent colons, or as an initial or trailing colon.

也就是说无论是前导的:或者结尾的:或者中间连续两个:(亦即::),都代表null目录,亦即当前目录。这样,我的疑问就彻底解决啦。

所以不是冒号(:)有魔力,而是自己学习不努力呀!2023年一定要努力学习,嗯,就这么定了,我先去抖音看一会美女去,回头就去学习!

(讲真,这些东西其实当年我上班时都会,怎么就忘得一干二净了呢?)

每天进步一点点:Linux动态库搜索路径 & 有魔力的冒号(:) | Ecency