为什么LD_PRELOAD没有使用没有shebang的脚本?

如果当我运行一个脚本时,我使用LD_PRELOAD来指定一个库来预加载,我发现只有当脚本有一个shebang行时,库才会被预加载。 例如,给定这个脚本:

 # Not a shebang echo Hello 

和这个命令:

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

该脚本运行时没有加载库,我可以通过它的初始化代码的(非)影响进行监视。

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

 #!/bin/sh echo Hello 

…当我通过相同的命令运行脚本时,库加载。 确切地说,哪个解释者是不明确的; 当然我也可以使用/bin/bash或者其他任何我尝试过的sh family。

为什么有区别,有没有什么方法可以确保给定的库在给定的shell简单命令之前被预加载,而不pipe命令如何?

(改编自另一个作者抵制这些问题的问题。)

(根据我提到的其他问题的答案进行调整。)

理解LD_PRELOAD变量对操作系统或shell没有特别的意义是很重要的。 它有意义和效果 – 如果它有它们 – 只与动态链接器一起使用。 如果动态链接器没有使用,那么LD_PRELOAD只是环境中的另一个变量。 同样,如果动态链接器不能识别该变量(例如,在OS X上)。

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

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

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