我正在使用 Bash
$ echo $SHELL
/bin/bash
从大约一年前开始,我停止在我的 Bash 脚本中使用 Shebangs。能
我受益于使用 #!/bin/sh
或 #!/bin/bash
?
更新:在某些情况下,文件仅被视为具有 舍邦,例子
$ cat foo.sh
ls
$ cat bar.sh
#!/bin/sh
ls
$ file foo.sh bar.sh
foo.sh: ASCII text
bar.sh: POSIX shell script, ASCII text executable
最佳答案
在类 UNIX 系统上,您应该始终以 shebang 行启动脚本。系统调用 execve
(负责启动程序)依赖于具有可执行文件头或 shebang 行的可执行文件。
来自 FreeBSD 的 execve manual page :
The execve() system call transforms the calling process into a new process. The new process is constructed from an ordinary file, whose name is pointed to by path, called the new process file. [...] This file is either an executable object file, or a file of data for an interpreter. [...] An interpreter file begins with a line of the form: #! interpreter [arg] When an interpreter file is execve'd, the system actually execve's the specified interpreter. If the optional arg is specified, it becomes the first argument to the interpreter, and the name of the originally execve'd file becomes the second argument
与Linux manual page 类似:
execve() executes the program pointed to by filename. filename must be either a binary executable, or a script starting with a line of the form:
#! interpreter [optional-arg]
事实上,如果一个文件的头部没有正确的“魔数(Magic Number)”(比如 ELF 头部或 #!
),execve
将 < em>因 ENOEXEC 错误而失败(同样来自 FreeBSD 的 execve 联机帮助页):
[ENOEXEC] The new process file has the appropriate access permission, but has an invalid magic number in its header.
如果文件具有可执行权限,但没有 shebang 行但看起来确实是文本文件,则行为取决于您运行的 shell。
大多数 shell 似乎会启动一个新的自身实例并将文件提供给它,见下文。
由于无法保证脚本实际上是为该 shell 编写的,因此这可能会成功或失败。
来自 tcsh(1) :
On systems which do not understand the `#!' script interpreter conven‐ tion the shell may be compiled to emulate it; see the version shell variable. If so, the shell checks the first line of the file to see if it is of the form `#!interpreter arg ...'. If it is, the shell starts interpreter with the given args and feeds the file to it on standard input.
来自 FreeBSD 的 sh(1) :
If the program is not a normal executable file (i.e., if it
does not begin with the “magic number” whose ASCII representation is
“#!”, resulting in an ENOEXEC return value from execve(2)) but appears to
be a text file, the shell will run a new instance of sh to interpret it.
来自 bash(1):
If this execution fails because the file is not in executable format, and the file is not a directory, it is assumed to be a shell script, a file containing shell commands. A subshell is spawned to execute it.
您不能总是依赖于非标准程序(如 bash)的位置。我在 /usr/bin
、/usr/local/bin
、/opt/fsf/bin
和 /中看到了 bash选择/gnu/bin
仅举几例。
所以通常使用env
是个好主意;
#!/usr/bin/env bash
如果您希望脚本可移植,请使用 sh
而不是 bash
。
#!/bin/sh
虽然像 POSIX 这样的标准不保证标准实用程序的绝对路径,但大多数类 UNIX 系统似乎在 /bin
中有 sh
和 env
在 /usr/bin
中。
关于bash - 我应该使用带有 Bash 脚本的 Shebang 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25165808/