我可以使用可变内容作为shebang吗?

Mar*_*ito 10 linux shell bash shell-script shebang

我有一个 shell 脚本,我想在其中添加一个 shebang。给定一个定义如下的变量:

SHEBANG="#!/bin/sh"
Run Code Online (Sandbox Code Playgroud)

我的问题是我是否可以在另一个脚本中使用该变量,如下所示:

$SHEBANG
# other stuff...
Run Code Online (Sandbox Code Playgroud)

Mic*_*mer 12

不可以。shebang 行由您的内核或系统库* 处理,不处理 shell 变量。

  • 如果您出于某种原因想使用环境变量作为解释器,您可以创建一个“蹦床”可执行文件(不是脚本!),重新生成$SHEBANG "$@". #!在这种情况下,您需要省略from 变量;#!仅当它是文件的前两个字节时才有用。

  • 另一种选择是利用这样一个事实,即没有 shebang 行的脚本将(通常)作为带有sh调用 shell 或调用 shell 的shell 脚本执行。如果您的 shebang 目标的注释语法与 shell 语法有用地重叠,则可以使其工作。这种策略现在或曾经在 Lisp 解释器中很常见。在您的示例中,解释器也是sh,这是不可行的。

  • 如果您可以依靠bash在场,则可以在该行上进一步推进:一个脚本,其第一行是

    exec /bin/bash -c 'exec "$SHEBANG" <(tail -n +2 "$0")' "$0" "$@"
    
    Run Code Online (Sandbox Code Playgroud)

    将适用于大多数口译员;Bash 用作中间步骤,因此可以使用进程替换tail为我们跳过第一行,这样我们就不会陷入无限循环。一些解释器要求文件是可查找的,他们不会接受这样的管道。


值得考虑这是否真的是你想做的事情。除了任何安全问题之外,它并不是很有用:很少有脚本可以像这样改变它们的解释器,并且在它们可以的地方,您几乎肯定会更好地使用更受限制的逻辑来为情况产生正确的逻辑(也许中间有一个 shell 脚本,它以真实脚本的路径作为参数调用解释器)。


* 并非总是如此;在某些情况下,一些 shell 会自己读取它,但它们仍然不会进行变量扩展。