https://zh.wikipedia.org/wiki/Shebang

在计算领域中,Shebang(也称为 Hashbang )是一个由井号和叹号构成的字符序列 #! ,其出现在文本文件的第一行的前两个字符。 在文件中存在 Shebang 的情况下,类 Unix 操作系统的程序加载器会分析 Shebang 后的内容,将这些内容作为解释器指令,并调用该指令,并将载有 Shebang 的文件路径作为该解释器的参数[1]。

例如,以指令#!/bin/sh开头的文件在执行时会实际调用/bin/sh程序(通常是 Bourne shell 或兼容的 shell,例如 bash、dash 等)来执行。这行内容也是 shell 脚本的标准起始行。

由于 # 符号在许多脚本语言中都是注释标识符,Shebang 的内容会被这些脚本解释器自动忽略。 在 # 字符不是注释标识符的语言中,例如 Scheme,解释器也可能忽略以 #! 开头的首行内容,以提供与 Shebang 的兼容性[2]。

“Shebang” 或者说 “Hashbang” 的名字有时也被当做 Ajax 应用程序中的 分段标识符,用于浏览器的状态保存;Google 网站站长中心提到,以叹号开头的分段标识符(即 …url#!state… )会为 Google 的网页爬虫所索引。

例子
下面列出了一些典型的 shebang 解释器指令:

#!/bin/sh—使用 sh,即 Bourne shell 或其它兼容 shell 执行脚本
#!/bin/csh—使用 csh,即 C shell 执行
#!/usr/bin/perl -w—使用带警告的 Perl 执行
#!/usr/bin/python -O—使用具有代码优化的 Python 执行
#!/usr/bin/php—使用 PHP 的命令行解释器执行

在许多系统上,/bin/sh 是链接到 Bash 的,而 /bin/csh 则是链接到 tcsh 的,因此设定前面的解释器实际上是运行的与之兼容的,或改进的版本。

Shebang 行也可以包含需要传递到解释器的特定选项(见下文的 Perl 例子)。然而,选项传递的方式随实现的不同而不同。

用途

解释器指令允许脚本和数据文件充当系统命令,无需在调用时由用户指定解释器,从而对用户和其它程序隐藏其实现细节。

假设 /usr/local/bin/foo 中有一以下行开头的 Bourne shell 脚本

#!/bin/sh -x

而它被如此调用(”$”是命令提示符)

$ foo bar

该命令的输出等同于

$ /bin/sh -x /usr/local/bin/foo bar

除了 argv[0] 被设定为脚本的文件名,而非解释器的文件名外。

由于 sh 从其命令行指定的文件中读取命令,上面的命令就会执行 /usr/local/bin/foo 中的命令,同时,将 bar作为foo 命令的参数 $1。

由于shebang开头的井号也是Bourne shell和许多其它解释性语言的注释符,因此在这些语言中,解释器指令本身会被解释器认为是单纯的注释而跳过。 然而,并不是每一种解释器都会自动忽略shebang行,例如对于下面的脚本,

#!/bin/cat
Hello world!

cat 会把文件中的两行都输出到标准输出中。

使用 #!/usr/bin/env 脚本解释器名称 是一种常见的在不同平台上都能正确找到解释器的办法。

Linux的操作系统的文件一般是UTF-8编码。如果脚本文件是以 UTF-8 的 BOM(0xEF 0xBB 0xBF) 开头的,那么 exec 函数将不会启动 shebang 指定的解释器来执行该脚本。因此,Linux 的脚本文件不应在文件开头包含 UTF-8 的 BOM。