LD_PRELOAD为什么不对没有shebang的脚本生效?

Joh*_*ger 5 linux bash elf ld-preload

如果,当我运行脚本时,我LD_PRELOAD用来指定要预加载的库,我发现只有当脚本有一个shebang行时才会预加载库.例如,给定此脚本:

# Not a shebang
echo Hello
Run Code Online (Sandbox Code Playgroud)

这个命令:

LD_PRELOAD=/path/to/preload_me.so ./script.sh
Run Code Online (Sandbox Code Playgroud)

该脚本在没有加载库的情况下运行,我可以通过其初始化代码的(非)效果进行监视.

另一方面,如果我添加一个shebang线:

#!/bin/sh
echo Hello
Run Code Online (Sandbox Code Playgroud)

... 当我通过相同的命令运行脚本时,库加载.似乎确切地指定了哪个解释器; 当然我也可以使用/bin/bash或任何其他sh- 我尝试过的家庭外壳.

为什么有区别,有没有办法确保给定的库在给定的shell简单命令之前预加载,而不管命令是什么?

(改编自另一个问题,其作者拒绝用这些术语表达的问题.)

Joh*_*ger 7

(改编自我对引用的其他问题的回答.)

必须了解LD_PRELOAD变量对操作系统或shell没有特殊意义.它有意义和影响 - 如果它有它们 - 只与动态链接器一起使用.如果没有使用动态链接器,那么LD_PRELOAD它只是环境中的另一个变量.同样,如果动态链接器不识别该变量(例如,在OS X上).

同样重要的是要理解,当执行名称对应于不是可执行格式但包含shebang行的文件的命令时,即使它是shell本身,也会执行指定的解释器.如果解释器是ELF二进制文件,那么它将使用动态链接器.另一方面,如果没有shebang行,则bash在子shell环境中执行文件的内容,这不需要使用动态链接器; 相反,shell只是分叉.其他shell可能会也可能不会这样做.

认识到存在除ELF之外的可执行格式也很重要.你不太可能在现代的基于ELF的系统上遇到这样的二进制文件,但你不应该排除这种可能性.

结论:无法确保在通过bash或用户选择的其他shell执行的任意shell命令的进程空间中预加载给定的动态库.如果您需要为任何或每个任意命令预加载这样的库,那么您需要更严格地控​​制执行环境,可能是通过提供自定义shell,也可能是自定义动态链接器,并防止使用任何其他命令.

  • 这是一个很好的答案,但我认为你应该澄清它特别适用于`bash`(可能还有其他shell).例如,`dash`似乎没有这样做.(它执行脚本,但预加载生效.)所有Posix都说"shell应该执行一个命令,该命令等同于使用搜索作为其第一个操作数产生的路径名调用shell",这可能适用于任一行为.(对我的系统进行快速测试:zsh预加载,ksh没有.去图.) (2认同)