如何#! shebang工作?
在脚本中你必须包含一个#!
在第一行,然后是执行脚本的程序的path(例如:sh,perl)。
据我所知, #
字符表示一个注释的开始,该行应该被执行该脚本的程序忽略。 看起来,这第一行是在某种程度上被某些东西读取,以便脚本被正确的程序执行。
请有人可以更多地了解#!
的运作#!
?
我真的很好奇,所以答案越深入越好。
推荐阅读:
- UNIX FAQ:为什么一些脚本以#开始! …?
- #! 魔术,关于各种Unix风格的shebang / hash-bang机制的细节
- 维基百科:Shebang
Unix内核的程序加载器负责这样做。 当调用exec()
,它会要求内核从文件的参数中加载程序。 然后它将检查文件的前16位,以查看它具有的可执行格式。 如果发现这些位是#!
它将使用文件第一行的其余部分来查找应该启动哪个程序,并提供正在尝试启动的文件的名称(脚本)作为解释程序的最后一个参数。
解释器然后运行正常,并对待#!
作为评论线。
小故事: shebang( #!
)行是由shell(例如读取的操作系统的程序加载器。 虽然它正式看起来像一个评论,事实上,它是一个文件的前两个字节标记整个文件作为文本文件和脚本。 该脚本将被传递到shebang之后的第一行中提到的可执行文件。 瞧! sh
, bash
等)
稍长的故事:想象一下你的脚本, foo.sh
,可执行位( x
)设置。 这个文件包含如下:
#!/bin/sh # some script commands follow...: # *snip*
现在,在你的shell中,input:
> ./foo.sh
编辑:请在阅读以下内容之前或之后阅读下面的评论! 事实certificate,我错了。 显然不是将脚本传递给目标解释器的shell,而是操作系统(内核)本身。
请记住,你在shell进程中键入这个(让我们假设这是程序/bin/sh
)。 因此,这个input必须由该程序处理。 它把这一行解释为一个命令,因为它发现在行上input的第一个东西是一个实际存在的文件的名字,并且有一个可执行的位被设置。
/bin/sh
然后开始读取文件的内容,并在文件的最开始处发现shebang( #!
)。 在shell中,这是一个令牌(“幻数”),通过它来知道该文件包含一个脚本。
现在,它如何知道脚本编写的是哪种编程语言呢? 毕竟,你可以执行Bash脚本,Perl脚本,Python脚本,…到目前为止,所有的shell都知道它正在查看一个脚本文件(这不是一个二进制文件,而是一个文本文件)。 因此它读取下一个input到第一个换行符(这将导致/bin/sh
,与上面的比较)。 这是脚本将通过执行的解释器。 (在这种情况下,目标解释器就是shell本身,所以它不必为脚本调用一个新的shell;它只是处理脚本文件本身的其余部分。)
如果脚本注定要用于/bin/perl
,那么Perl解释器(可选)所要做的就是查看shebang行是否真的提到了Perl解释器。 如果没有,Perl解释器会知道它不能执行这个脚本。 如果确实在shebang行中提到了Perl解释器,它将读取脚本文件的其余部分并执行它。
Linux内核exec
系统调用使用初始字节#!
识别文件types
当你在bash上做:
./something
在Linux上,这将调用具有完整path的exec
系统调用。
这行被传递给exec
的文件在内核中调用: https : //github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25
if((bprm-> buf [0]!='#')||(bprm-> buf [1]!='!'))
它读取文件的第一个字节,并将它们与#!
进行比较 。
如果比较结果是真的,那么剩下的内容由Linux内核parsing,这个内核调用path/usr/bin/env python
和当前文件作为第一个参数:
/usr/bin/env python /path/to/script.py
这适用于任何使用#
作为注释字符的脚本语言。
是的,你可以做一个无限循环:
#!/a
和path/a
的可执行文件
#!
是人类可读的,但这不是必需的。
如果文件以不同的字节开始,那么exec
系统调用将使用不同的处理程序。 另一个最重要的内置处理程序是用于ELF可执行文件: https : //github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305它检查字节7f 45 4c 46
(也是碰巧是人类可读的.ELF
),它读取elf文件,将其正确存入内存,并开始一个新的进程。 另请参阅: 内核如何获得在Linux下运行的可执行二进制文件?
另外,您可以添加您自己的shebang处理程序binfmt_misc
机制。 例如,您可以为.jar
文件添加一个自定义处理程序: 运行JAR文件而不直接调用java这个机制甚至通过文件扩展来支持处理程序。 http://stackoverflow.com/questions/3009192/how-does-the-shebang-work/40938907#40938907
我不认为POSIX指定shebangs: https ://unix.stackexchange.com/a/346214/32558