对于大多数用途而言,客观上是否有任何 Bash
shebang 比其他更好?
#!/usr/bin/env bash
#!/bin/bash
#!/bin/sh
#!/bin/sh -
ETC
我隐约记得很久以前听说在末尾添加破折号可以防止有人将命令传递给您的脚本,但找不到任何详细信息。
/usr/local/bin/bash
。
#!/usr/bin/env bash
会造成权限提升安全威胁。用户可以简单地操纵他的 PATH
并获得一个任意的 bash 可执行文件来运行,并具有提升的权限。
您应该为 portability 使用 #!/usr/bin/env bash
:不同的 *nixes 将 bash
放在不同的位置,使用 /usr/bin/env
是运行在 PATH
上找到的第一个 bash
的解决方法.还有sh
is not bash
。
我建议使用:
#!/bin/bash
它不是 100% 可移植的(某些系统将 bash
放置在 /bin
以外的位置),但许多现有脚本使用 #!/bin/bash
的事实迫使各种操作系统使 /bin/bash
至少成为指向主要位置。
替代方案:
#!/usr/bin/env bash
已建议 - 但不能保证 env
命令在 /usr/bin
中(而且我使用了不在的系统)。此外,此表单将使用当前用户 $PATH
中的第一个 bash
实例,这可能不是 bash shell 的合适版本。
(但是 /usr/bin/env
应该可以在任何相当现代的系统上运行,要么是因为 env
在 /usr/bin
中,要么是因为系统做了一些事情来使它工作。我上面提到的系统是 SunOS 4,我可能还没有使用了大约 25 年。)
如果您需要在没有 /bin/bash
的系统上运行脚本,您可以修改脚本以指向正确的位置(这确实不方便)。
我在 my answer 到 this question 中更深入地讨论了权衡。
一个有点模糊的更新:我使用的一个系统,Termux,一个在 Android 下运行的类似桌面 Linux 的层,没有 /bin/bash
(bash
是 /data/data/com.termux/files/usr/bin/bash
)——但它有特殊处理支持#!/bin/bash
。
/bin/sh
通常是指向系统默认 shell 的链接,它通常是 bash
,但在例如 Debian 系统上是较轻的 dash
。无论哪种方式,原始 Bourne shell 都是 sh
,因此如果您的脚本使用一些 bash
(第二代,“Bourne Again sh”)特定功能([[ ]]
测试、数组、各种含糖的东西等),那么您应该更具体并使用后者。这样,在未安装 bash 的系统上,您的脚本将不会运行。我知道可能会有一部关于这种演变的激动人心的电影三部曲……但这可能是传闻。
另请注意,当作为 sh
唤起时,bash
在某种程度上是 behaves as POSIX standard sh
(另请参见 the GNU docs)。
/bin/sh
链接到 /usr
中的任何位置,因为这会使 init 脚本在安装 /usr
之前运行起来相当困难。
/bin
和 /sbin
多年来一直是默认的符号链接,指向 /usr/bin
和 /usr/sbin
,因此在该上下文中,/bin/sh
是指向 bash
的链接,实际目录是 /usr/bin
。但我会更正上面的。
使用 shebang 行调用适当的解释器不仅适用于 BASH。您可以将 shebang 用于系统上的任何解释语言,例如 Perl、Python、PHP (CLI) 和许多其他语言。顺便说一句,shebang
#!/bin/sh -
(它也可以是两个破折号,即 --
)结束 bash 选项之后的所有内容都将被视为文件名和参数。
使用 env
命令使您的脚本可移植,并允许您为脚本设置自定义环境,因此可移植脚本应使用
#!/usr/bin/env bash
或者对于任何语言,例如 Perl
#!/usr/bin/env perl
请务必查看 bash
的 man
页:
man bash
和env
:
man env
注意:在 Debian 和基于 Debian 的系统(如 Ubuntu)上,sh
链接到 dash
而不是 bash
。因为所有系统脚本都使用 sh
。根据 Debian 的说法,这允许 bash 增长并使系统保持稳定。
此外,为了保持调用 *nix 就像我从不在 shebang 调用的脚本上使用文件扩展名一样,因为你不能像在 Windows 上那样省略可执行文件调用的扩展名。 file 命令可以将其识别为脚本。
这实际上取决于您如何编写 bash 脚本。如果您的 /bin/sh
符号链接到 bash,则当 bash 作为 sh
调用时,some features are unavailable。
如果您想要特定于 bash 的非 POSIX 功能,请使用 #!/bin/bash
pkg_add
安装它,那么它位于 /usr/local/bin
,它可能不在路径上。
POSIX
功能怎么样?
为 #!/usr/bin/env 方法再投一票。我经常使用虚拟环境,就我而言,我使用安装在 virtualenv 中的 python。使用 #!/usr/bin/python 可能不是我想要的 python。我使用 #!/usr/bin/env python 得到了正确的 python。
#!/bin/sh
因为大多数脚本不需要特定的 bash 功能,应该为 sh 编写。
此外,这使得脚本可以在默认情况下没有 bash 的 BSD 上运行。
sh
and bash
/bin/sh
是否是 bash 脚本的好方法。所以我认为 weberjn 的答案并没有超出范围。
不定期副业成功案例分享
/bin/sh
等),这显然仅对防止在命令行上将恶意参数传递给脚本有用。bash
并非在所有系统上都存在于/bin
中。alias shebang='echo "#!/usr/bin/env bash"'
,现在我只需要打开终端并输入 shebang 而不是去这里。env
在/usr/bin/env
。它可以在/bin/env
或实际上任何地方,只要它在路径中。如果/dummy
在PATH
中,它可能在/dummy/env
。 Shebang 本身在 POSIX 下是未定义的,所以我可以让#!stop toaster
启动 USB 咖啡机并符合 POSIX。所以#!/usr/bin/env bash
并不比#!/bin/bash
特别好,它可能不太便携,具体取决于。/usr/bin/env
存在于比/bin/bash
xor/usr/bin/bash
更多的机器上,因此以该行开头的脚本将在尽可能多的机器上执行预期的操作。