33

我正在编写一个简单的 shell 脚本,发现我的 shell 脚本不需要 shebang 行

#!/bin/sh

如果我为我的脚本授予执行权限并使用./myscript.sh. 它运行良好。

我正在使用bashshell,/bin/sh实际上是指向bash.

lrwxrwxrwx 1 root root /bin/sh -> bash

我知道 shebang 行用于告诉 shell 哪个解释器用于脚本的其余部分。

如果我错过了 perl 中的 shebang 行,请授予执行权限并运行./myscript.pl,它不起作用。

这里到底发生了什么?如果我使用./,什么时候真正需要 shebang 线?

4

3 回答 3

32

您输入的父外壳程序./myscript.sh首先尝试了execve它,如果存在的话,shebang 行将在其中生效。当这工作时,父级不知道脚本和 ELF 之间的区别,因为内核会处理它。

execve失败了,所以一个古老的 unix 兼容性功能,早于 shebang 行的存在,就被激活了。它猜测具有执行权限但未被内核识别为有效可执行文件的文件一定是shell脚本。

通常父 shell 猜测脚本是为同一个 shell 编写的(最小的 Bourne-like shell 使用 运行脚本/bin/sh,bash 将其作为 bash 子进程运行), csh 基于第一个字符进行一些更复杂的猜测,因为它也早于 shebang并且它需要与 Bourne shell 共存)。

当您知道这些猜测是错误的(例如使用 shebang is #!/usr/bin/perl),或者当您不相信猜测能够始终如一地工作,或者当脚本需要由不是的父进程运行时,您需要一个 shebang 行壳本身。

于 2012-09-06T09:16:11.167 回答
18

文件中需要 shebang 行,并且仅当它打算作为可执行文件运行时(与sh file.sh调用相反。脚本实际上不需要它,它是让系统知道如何找到解释器。

编辑:很抱歉误读了这个问题。如果 shebang 行丢失或无法识别,/bin/sh则使用。但我更喜欢明确解释解释器。

请注意,这种行为不是通用的,IIRC,只有一些exec*家庭功能可以这样做(更不用说不同的平台),所以这是在这里明确的另一个原因。

于 2012-09-06T08:51:51.193 回答
4

POSIX(单一 UNIX 规范 4)标准没有帮助:

如果 shell 命令文件的第一行以字符“#!”开头 ,结果未指定。

因此,标准意味着如果您没有 #! 那么它应该运行一个 POSIX shell。但是现代 shell 不符合 POSIX。旧的 Korn Shell 88 (ksh88) 运行 Bourne shell(接近 POSIX shell),没有 #! 行,但 ksh93 打破了这一点,Bash 也是如此。使用 ksh93 和 Bash,如果没有 #! 线存在。

尽管流行的观点,Bash 和 Korn shell 不同。当你编写一个 shell 脚本时,你永远无法确定你将从哪个 shell 运行,或者即使它会从另一个 shell 运行(大多数编程语言可以运行其他程序)。一旦你使用了 Bourne/POSIX 语法之外的东西,你就会被淹没。

始终使用 #! 线,不要让它碰运气。

于 2012-09-06T09:24:43.687 回答