【问题标题】:Why doesn't LD_PRELOAD take effect with scripts having no shebang?为什么 LD_PRELOAD 对没有 shebang 的脚本不生效?
【发布时间】:2017-02-20 07:34:41
【问题描述】:

如果我在运行脚本时使用LD_PRELOAD 指定要预加载的库,我发现该库实际上只有在脚本有shebang 行时才被预加载。例如,给定这个脚本:

# Not a shebang
echo Hello

还有这个命令:

LD_PRELOAD=/path/to/preload_me.so ./script.sh

脚本在完全没有加载库的情况下运行,我可以通过其初始化代码的(非)影响来监控它。

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

#!/bin/sh
echo Hello

...然后当我通过相同的命令运行脚本时,库 is 已加载。指定哪个解释器似乎并不重要。当然我也可以使用/bin/bash 或我尝试过的任何其他sh-family shell。

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

(改编自another question,其作者拒绝用这些术语提出问题。)

【问题讨论】:

    标签: linux bash elf ld-preload


    【解决方案1】:

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

    必须了解LD_PRELOAD 变量对操作系统或shell 没有特殊意义。它只有在与动态链接器结合使用时才有意义和效果——如果它有的话。如果没有使用动态链接器,那么LD_PRELOAD 只是环境中的另一个变量。同样,如果动态链接器无法识别该变量(例如在 OS X 上)。

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

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

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

    【讨论】:

    • 这是一个很好的答案,但我认为您应该澄清它专门适用于bash(可能还有其他shell。)dash 似乎没有这样做,例如。 (它执行脚本,但预加载生效。)所有 Posix 都说“shell 应执行一个命令,相当于调用一个 shell,将搜索产生的路径名作为其第一个操作数”,这可能适用于任何一种行为。 (在我的系统上快速测试:zsh 预加载,ksh 没有。去看看。)
    • @rici,答案确实明确表示 bash 分叉而不是执行新的 shell 进程,但我仍然添加了一个说明。
    猜你喜欢
    • 1970-01-01
    • 2012-08-31
    • 2012-04-14
    • 2019-10-02
    • 2015-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-16
    相关资源
    最近更新 更多