Shebang
在计算领域中,Shebang(也称为Hashbang)是一个由井号和叹号构成的字符序列#!
,其出现在文本文件的第一行的前两个字符。
在文件中存在Shebang的情况下,类Unix操作系统的程序加载器会分析Shebang后的内容,将这些内容作为解释器指令,并调用该指令,并将载有Shebang的文件路径作为该解释器的参数[1][2]。
例如,以指令#!/bin/sh
开头的文件在执行时会实际调用/bin/sh程序(通常是Bourne shell或兼容的shell,例如bash、dash等)来执行。这行内容也是shell脚本的标准起始行。
由于#
符号在许多脚本语言中都是注释标识符,Shebang的内容会被这些脚本解释器自动忽略。
在#
字符不是注释标识符的语言中,例如Scheme,解释器也可能忽略以#!
开头的首行内容,以提供与Shebang的兼容性[3]。
"Shebang"或者说"Hashbang"的名字有时也被当做Ajax应用程序中的分段标识符,用于浏览器的状态保存;Google网站站长中心提到,以叹号开头的分段标识符(即...url#!state...)会为Google的网页爬虫所索引。
语法
Shebang这一语法特性由#!
开头,即井号和叹号。
在开头字符之后,可以有一个或数个空白字符,后接解释器的绝对路径,用于调用解释器。
在直接调用脚本时,调用者会利用Shebang提供的信息调用相应的解释器,从而使得脚本文件的调用方式与普通的可执行文件类似。
词源与历史
Shebang的名字来自于SHArp和bang,或haSH bang的缩写,指代Shebang中#!
两个符号的典型Unix名称。
Unix术语中,井号通常称为sharp,hash或mesh;而叹号则常常称为bang。也有看法认为,shebang名字中的sh来自于默认shell————Bourne shell的名称,sh
,因为常常使用shebang调用之。[4][1]
在2010年版的Advanced bash scripting guide(页面存档备份,存于互联网档案馆)(revision 6.2)中,shebang被称为"sha-bang",同时提到"也写作she-bang或sh-bang",但该文件中没有提到"shebang"这一形式。[1]
丹尼斯·里奇在被问及他会如何称呼这一特性时,他答道:
发信人:"Ritchie, Dennis M (Dennis)** CTR **" <dmr@[redacted]>
收信人:<[redacted]@talisman.org>
日期:Thu, 19 Nov 2009 18:37:37 -0600
主题:RE: What do -you- call your #!<something> line?
我不记得我们曾经给它取过一个适当的名字。导入这一特性已经是相当晚了--我觉得我是从关于伯克利Unix的UCB会议上的某人那里得到的这一灵感;我可能是首先实现它的人之一,但这个创意是来自于别人的。
至于它的名字:可能是类似于"hash-bang"的英国风描述性文字,但我没有在任何场合使用类似宠物的名字来描述它。
此致,
Dennis
例子
下面列出了一些典型的 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行,例如对于下面的脚本,cat
会把文件中的两行都输出到标准输出中。
#!/bin/cat
Hello world!
使用#!/usr/bin/env 脚本解释器名称
是一种常见的在不同平台上都能正确找到解释器的办法。
Linux的操作系统的文件一般是UTF-8编码。如果脚本文件是以UTF-8的BOM(0xEF 0xBB 0xBF)
开头的,那么exec函数将不会启动shebang指定的解释器来执行该脚本。因此,Linux的脚本文件不应在文件开头包含UTF-8的BOM。
参见
- CrunchBang Linux,一种GNU/Linux发行版
- 文件关联
参考文献
- ^ 1.0 1.1 1.2 Advanced Bash Scripting Guide: Chapter 2. Starting Off With a Sha-Bang. [2019-12-10]. (原始内容存档于2019-12-10).
- ^ execve(2) - Linux man page. [2010-10-21]. (原始内容存档于2010-11-02).
- ^ Martin Gasbichler and Michael Sperber. SRFI 22: Running Scheme Scripts on Unix. [2011-03-19]. (原始内容存档于2011-02-27).
- ^ Jargon File entry for shebang. Catb.org. [2010-06-16]. (原始内容存档于2011-06-04).
外部链接
- Details about the shebang mechanism on various Unix flavours(页面存档备份,存于互联网档案馆)
- #! - the Unix truth as far as I know it(页面存档备份,存于互联网档案馆)(a more generic approach)
- FOLDOC shebang article