shebang 标志与设置内置标志之间的区别

Difference between shebang flags vs. set builtin flags

关于在 shebang 行上传递给脚本的标志与使用 set 内置函数的行为是否存在差异?

例如:

#!/bin/bash -e

# do stuff

对比

#!/bin/bash
set -e
# do stuff

(问题不是特定于 -e 标志,而是一般针对任何此类标志)。

显然 set [flags] 仅在设置时有效。但是functionality/behaviour还有其他区别吗?

POSIX shell 中的行为也一样吗?

联机帮助页指出“-e”根据 POSIX 模式有不同的行为。 除此之外,我从未注意到设置参数和扩展 shebang 之间的区别。 你为什么问这个问题?

一些操作系统可能不允许或限制在 shebang 中使用参数。没有这样的限制将适用于脚本本身的 set 命令。

are there any other differences in functionality/behaviour?

当您的文件具有可执行权限并被执行时,内核会解析 shebang 行。

当您的文件在 bash ./script.sh 之类的 shell 下执行时,shebang 只是一个注释。因此它将被忽略,并且您的脚本将 运行 与调用者标志是什么。在 shebang 之后放置你的标志将确保在任何情况下都在你的脚本中设置正确的标志。

shebang 是 parsed by kernel. That basically means that the behavior differs from kernel to kernel, from operating system to operating system. Some operating systems didn't handle arguments in shebang at all and ignored all the arguments. Some kernels parse for example #!/bin/sh -a -b as execl("/bin/sh", "-a -b") some as execl("/bin/sh", "-a", "-b"). The parsing of the shebang line to executable and arguments is done by some other code different that your shell. Sometimes if there is a space after #! like #! /bin/sh utilities don't recognize it as a valid shebang. There's even a recent linux kernel regression with too long shebang line

shebang 的解释方式因系统而异,因此您无法确定,因此最好在 shebang 之后 set 选项。

Is behaviour same in a POSIX shell, too?

A POSIX shell 不会(必须)解释您的 shebang。如果您询问执行 sh -eset -e 在 posix shell 中是否具有相同的行为,那么 yes, the option -e on command lineset -e 具有相同的行为。

我找不到 shebang 行的规范,也找不到如何在 posix specification 中解释它。我可以在 execve 文档中看到:

Another way that some historical implementations handle shell scripts is by recognizing the first two bytes of the file as the character string "#!" and using the remainder of the first line of the file as the name of the command interpreter to execute.

那些“历史实现”似乎在今天仍然被广泛使用。

shebang 行在 exec* 调用后由内核解析。但是当你做 sh <script>popensystemshell can (但不必)将 shebang 行本身解释为扩展而不依赖于内核实现,来自 posix:

Shell Introduction

  1. The shell reads its input from a file (see sh), from the −c option or from the system() and popen() functions defined in the System Interfaces volume of POSIX.1-200x. If the first line of a file of shell commands starts with the characters"#!",the results are unspecified.

至于bash,貌似bashfirst tries execve, then if it can't find the reason why kernel failed to run the executable, if the file has a shebang, then it parses shebang on its own找解释器