我刚刚下载了一个tar
文件,该文件应该包含运行我们可以调用的程序所需的所有内容some_binary
。我提取了它的内容,我看到以下内容:
- 一个二进制文件(我们称之为
some_binary
) - 包含各种动态库(.so 文件)的文件夹
lib
,例如/lib/ld-linux-x86-64.so
- 和一个名为的 shell 脚本
some_binary.sh
该脚本有以下内容:
#!/bin/bash
`dirname "$0"`/lib/ld-linux-x86-64.so.2 `dirname "$0"`/some_binary "$@"
并运行它似乎./some_binary.sh some arguments
运行./some_binary
正确。奇怪的是,运行以下脚本:
#!/bin/bash
LD_LIBRARY_PATH=$CWD/LIB:$LD_LIBRARY_PATH
./some_binary "$@"
因为./my_script.sh some arguments
不起作用。它会导致重定位错误(未定义的符号),可能是由于错误地加载了下面的库./lib
此外,从命令行运行以下两个语句会导致segmentation fault
:
> LD_LIBRARY_PATH=$CWD/LIB:$LD_LIBRARY_PATH
> ./some_binary some arguments
对此,我的问题是:
- 第一个脚本的作用是什么?
- 为什么我在这三种尝试中得到不同的结果?为什么我不能直接添加
$pwd/lib
然后LD_LIBRARY_PATH
运行some_binary
?
答案1
该程序带有自己的动态加载器。程序很少需要自己的动态加载器:通常您系统上的动态加载器也可以工作。如果程序链接到 GNU libc 之外的标准库,或者链接到使用奇怪设置编译的 GNU libc,则这可能是必要的。
告诉加载程序在哪里可以找到程序的首选库就足够了。你的尝试几乎做到了这一点,但不完全是。如果LD_LIBRARY_PATH
环境中尚不存在,则赋值LD_LIBRARY_PATH=$CWD/LIB:$LD_LIBRARY_PATH
仅定义了 shell 变量,而不是环境变量,因此程序看不到任何东西。此外,$CWD
通常会扩展为空字符串,您可能指的是$PWD
或更好$(dirname "$0")
(即包含脚本的目录)。另请注意,您在问题中使用了lib
和不一致的内容。LIB
尝试
#!/bin/sh
export LD_LIBRARY_PATH="$(dirname "$0")/lib:$LD_LIBRARY_PATH"
exec "$(dirname "$0")/some_binary" "$@"
或者更好的是,如果之前没有定义,则避免在末尾有一个空条目LD_LIBRARY_PATH
(这可能很糟糕,因为空条目代表当前目录,尽管在路径末尾,只有在库不存在时才有害)没有找到它应该在的地方):
#!/bin/sh
export LD_LIBRARY_PATH="$(dirname "$0")/lib:$LD_LIBRARY_PATH"
case "$LD_LIBRARY_PATH" in *:) LD_LIBRARY_PATH=${LD_LIBRARY_PATH%:};; esac
exec "$(dirname "$0")/some_binary" "$@"