我应该在Bash脚本中使用Shebang吗?
我正在使用Bash我应该在Bash脚本中使用Shebang吗?,bash,shell,sh,shebang,Bash,Shell,Sh,Shebang,我正在使用Bash $ echo $SHELL /bin/bash 从大约一年前开始,我停止在Bash脚本中使用Shebangs。可以 我从使用#中获益/bin/sh或#/bin/bash 更新:在某些情况下,文件仅被视为具有 例如,Shebang $ 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 e
$ echo $SHELL
/bin/bash
从大约一年前开始,我停止在Bash脚本中使用Shebangs。可以
我从使用#中获益/bin/sh
或#/bin/bash
更新:在某些情况下,文件仅被视为具有
例如,Shebang
$ 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
脚本应始终以shebang行开头。如果脚本没有以此开头,那么它可能由当前shell执行。但这意味着,如果使用您的脚本的人运行的shell与您不同,则脚本的行为可能会有所不同。此外,这意味着脚本不能直接从程序运行(例如,C
exec()
系统调用,或find-exec
),它必须从shell运行。标头很有用,因为它指定了运行脚本时要使用的shell。例如,#/bin/zsh
会将shell改为zsh而不是bash,在这里可以使用不同的命令
例如,指定以下内容:
使用#/bin/sh,大多数商业变体中的默认Bourne shell
对于UNIX,使脚本可移植到非Linux机器,但
牺牲Bash的特定功能
在类UNIX系统上,应该始终使用shebang行启动脚本。系统调用execve(负责启动程序)依赖于具有可执行头或shebang行的可执行文件 从FreeBSD的:
execve()系统调用将调用进程转换为新的
过程新进程是从一个普通文件构造的,该文件
名称由路径指向,称为新进程文件。
[...]
这个文件是
可执行对象文件,或解释器的数据文件。
[...]
解释器文件以以下形式的行开始:
#! 解释器[arg]
当解释器文件被执行时,系统实际上是执行的
指定的解释器。如果指定了可选参数,则它将成为
解释器的第一个参数,以及
execve'd文件成为第二个参数
同样,从以下方面:
execve()执行文件名指向的程序。文件名必须为
可以是二进制可执行文件,也可以是以
表格:
#!解释器[可选参数]
事实上,如果文件头中没有正确的“幻数”(如ELF头或#!
),execve
将失败,并出现ENOEXEC错误(同样来自FreeBSD的execve手册页):
[ENOEXEC]新流程文件具有适当的访问权限
权限,但其中有无效的幻数
标题
如果文件具有可执行权限,但没有shebang行,但看起来确实是文本文件,那么行为取决于您运行的shell 大多数shell似乎会启动自己的新实例并将其提供给文件,请参见下文 由于无法保证脚本是为该shell编写的,因此这可能会成功,也可能会失败 发件人:
在不理解`#!'的系统上脚本解释器会议
可以编译shell以模拟它;请参阅shell的版本
变量如果是,shell将检查文件的第一行,以确定
它的形式是`#!解释器arg…'。如果是,外壳将启动
具有给定参数的解释器,并将文件按标准格式提供给它
输入。
从FreeBSD的:
如果程序不是正常的可执行文件(即
不以ASCII表示为的“幻数”开头
“#!”,从execve(2)中得到一个ENOEXEC返回值),但似乎
如果是文本文件,shell将运行一个新的sh实例来解释它。
来自bash(1):
如果由于文件不是可执行格式而导致执行失败,
并且该文件不是一个目录,它被假定为一个shell脚本,一个
包含shell命令的文件。生成一个子shell来执行它。
您不能总是依赖于非标准程序(如bash)的位置。我在
/usr/bin
、/usr/local/bin
、/opt/fsf/bin
和/opt/gnu/bin
中见过bash
因此,通常最好使用env
#/usr/bin/env bash
如果希望脚本可移植,请使用sh
而不是bash
#/垃圾箱/垃圾箱
虽然POSIX等标准不能保证标准实用程序的绝对路径,但大多数类UNIX系统似乎在/bin
中有sh
,在/usr/bin
中有env
#/bin/bash
shebang只是为了确保使用了正确的解释器。您不应该用#替换shebang/bin/sh
因为bash将在POSIX模式下运行,所以某些脚本的行为可能会有所不同#/您的系统上的bin/sh
(即,/bin/sh
是POSIX外壳的系统)/bin/sh
成为符合POSIX的shell,因此没有可移植的方法来指定其在shebang中的路径。在第三种情况下,为了能够在无法运行shebangless可执行脚本的系统上使用'find-exec'语法,您只需在
find /tmp -name "*.foo" -exec sh -c 'myscript "$@"' sh {} +
#! /bin/sh
root@kali:~/Desktop# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash