如何#! shebang工作?

在脚本中你必须包含一个#! 在第一行,然后是执行脚本的程序的path(例如:sh,perl)。

据我所知, #字符表示一个注释的开始,该行应该被执行该脚本的程序忽略。 看起来,这第一行是在某种程度上被某些东西读取,以便脚本被正确的程序执行。

请有人可以更多地了解#!的运作#!

我真的很好奇,所以答案越深入越好。

推荐阅读:

  • UNIX FAQ:为什么一些脚本以#开始! …?
  • #! 魔术,关于各种Unix风格的shebang / hash-bang机制的细节
  • 维基百科:Shebang

Unix内核的程序加载器负责这样做。 当调用exec() ,它会要求内核从文件的参数中加载程序。 然后它将检查文件的前16位,以查看它具有的可执行格式。 如果发现这些位是#! 它将使用文件第一行的其余部分来查找应该启动哪个程序,并提供正在尝试启动的文件的名称(脚本)作为解释程序的最后一个参数。

解释器然后运行正常,并对待#! 作为评论线。

小故事: shebang( #! )行是由shell(例如shbash等)读取的操作系统的程序加载器。 虽然它正式看起来像一个评论,事实上,它是一个文件的前两个字节标记整个文件作为文本文件和脚本。 该脚本将被传递到shebang之后的第一行中提到的可执行文件。 瞧!


稍长的故事:想象一下你的脚本, 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