ChatGPT解决这个技术问题 Extra ChatGPT

首选的 Bash shebang 是什么?

对于大多数用途而言,客观上是否有任何 Bash shebang 比其他更好?

#!/usr/bin/env bash

#!/bin/bash

#!/bin/sh

#!/bin/sh -

ETC

我隐约记得很久以前听说在末尾添加破折号可以防止有人将命令传递给您的脚本,但找不到任何详细信息。

以及它在 OpenBSD 上的 /usr/local/bin/bash
添加破折号是为了防止某种 setuid root 欺骗攻击,请参阅 security.stackexchange.com/questions/45490/…
我会对此表示赞成,但它的得分为 1337,我不想打扰它!
当 suid 程序执行具有这种 shebang 的 bash 脚本时,#!/usr/bin/env bash 会造成权限提升安全威胁。用户可以简单地操纵他的 PATH 并获得一个任意的 bash 可执行文件来运行,并具有提升的权限。

l
l0b0

您应该为 portability 使用 #!/usr/bin/env bash:不同的 *nixes 将 bash 放在不同的位置,使用 /usr/bin/env 是运行在 PATH 上找到的第一个 bash 的解决方法.还有sh is not bash


谢谢。看起来也像在 $!/usr/bin/env bash 的末尾添加 - 不会做任何事情,因为 *nix 在 shebang 中只允许一个参数,并且由 'bash' 使用。如果脚本的 shebang 是其他没有参数的脚本之一(/bin/sh 等),这显然仅对防止在命令行上将恶意参数传递给脚本有用。
@Ray bash 并非在所有系统上都存在于 /bin 中。
我也一样,我只是将它添加到别名:alias shebang='echo "#!/usr/bin/env bash"',现在我只需要打开终端并输入 shebang 而不是去这里。
这个答案是骗人的。 POSIX 没有说 env/usr/bin/env。它可以在 /bin/env 或实际上任何地方,只要它在路径中。如果 /dummyPATH 中,它可能在 /dummy/env。 Shebang 本身在 POSIX 下是未定义的,所以我可以让 #!stop toaster 启动 USB 咖啡机并符合 POSIX。所以 #!/usr/bin/env bash 并不比 #!/bin/bash 特别好,它可能不太便携,具体取决于。
@darkfeline 可移植性不是绝对的——在数学上不可能制作任何在每个平台上都做同样事情的脚本。从 2012 年到 2018 年,/usr/bin/env 存在于比 /bin/bash xor /usr/bin/bash 更多的机器上,因此以该行开头的脚本将在尽可能多的机器上执行预期的操作。
K
Keith Thompson

我建议使用:

#!/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 answerthis question 中更深入地讨论了权衡。

一个有点模糊的更新:我使用的一个系统,Termux,一个在 Android 下运行的类似桌面 Linux 的层,没有 /bin/bashbash/data/data/com.termux/files/usr/bin/bash)——但它有特殊处理支持#!/bin/bash


年后,这仍然是这里最好的建议。如果简单的解决方案不起作用,那么您必须质疑您之前的决定。被接受和最赞成的答案没有错,只是不对:)
C
CodeClown42

/bin/sh 通常是指向系统默认 shell 的链接,它通常是 bash,但在例如 Debian 系统上是较轻的 dash。无论哪种方式,原始 Bourne shell 都是 sh,因此如果您的脚本使用一些 bash(第二代,“Bourne Again sh”)特定功能([[ ]] 测试、数组、各种含糖的东西等),那么您应该更具体并使用后者。这样,在未安装 bash 的系统上,您的脚本将不会运行。我知道可能会有一部关于这种演变的激动人心的电影三部曲……但这可能是传闻。

另请注意,当作为 sh 唤起时,bash 在某种程度上是 behaves as POSIX standard sh(另请参见 the GNU docs)。


Public Domain Korn Shell (pdksh) 是 OpenBSD 的默认设置。
大多数系统不会/bin/sh 链接到 /usr 中的任何位置,因为这会使 init 脚本在安装 /usr 之前运行起来相当困难。
@aij 我不知道为什么我把“很多或大多数”放在那里——我是一个 Fedora 用户,其中 /bin/sbin 多年来一直是默认的符号链接,指向 /usr/bin/usr/sbin ,因此在该上下文中,/bin/sh 是指向 bash 的链接,实际目录是 /usr/bin。但我会更正上面的。
n
nbro

使用 shebang 行调用适当的解释器不仅适用于 BASH。您可以将 shebang 用于系统上的任何解释语言,例如 Perl、Python、PHP (CLI) 和许多其他语言。顺便说一句,shebang

#!/bin/sh -

(它也可以是两个破折号,即 --)结束 bash 选项之后的所有内容都将被视为文件名和参数。

使用 env 命令使您的脚本可移植,并允许您为脚本设置自定义环境,因此可移植脚本应使用

#!/usr/bin/env bash

或者对于任何语言,例如 Perl

#!/usr/bin/env perl

请务必查看 bashman 页:

man bash

env

man env

注意:在 Debian 和基于 Debian 的系统(如 Ubuntu)上,sh 链接到 dash 而不是 bash。因为所有系统脚本都使用 sh。根据 Debian 的说法,这允许 bash 增长并使系统保持稳定。

此外,为了保持调用 *nix 就像我从不在 shebang 调用的脚本上使用文件扩展名一样,因为你不能像在 Windows 上那样省略可执行文件调用的扩展名。 file 命令可以将其识别为脚本。


N
Nathan Smith

这实际上取决于您如何编写 bash 脚本。如果您的 /bin/sh 符号链接到 bash,则当 bash 作为 sh 调用时,some features are unavailable

如果您想要特定于 bash 的非 POSIX 功能,请使用 #!/bin/bash


OpenBSD 上没有安装 Bash。如果您通过 pkg_add 安装它,那么它位于 /usr/local/bin,它可能不在路径上。
POSIX 功能怎么样?
T
Tom Ekberg

为 #!/usr/bin/env 方法再投一票。我经常使用虚拟环境,就我而言,我使用安装在 virtualenv 中的 python。使用 #!/usr/bin/python 可能不是我想要的 python。我使用 #!/usr/bin/env python 得到了正确的 python。


请回答问题:这是调用 bash 脚本而不是 pythong 脚本的最佳方式。两者都有截然不同的要求,因为 bash 位置始终位于 /bin 下(与 virtualenv 中的 python 相反)并且 python 版本不兼容,而 bash 脚本通常会与任何最近的 bash 版本一起运行。不是同一个问题空间。毕竟这是关于 bash 的,而不是关于 python 的。
w
weberjn

#!/bin/sh

因为大多数脚本不需要特定的 bash 功能,应该为 sh 编写。

此外,这使得脚本可以在默认情况下没有 bash 的 BSD 上运行。


但问题是 Bash 脚本具体使用什么。这有一个明显且潜在的严重缺点,即它不适用于 Bash 脚本(即任何使用 Bash-only 功能的东西)。对于新手来说,这是一个常见的陷阱。另请参阅Difference between sh and bash
问这个问题的人专门询问 /bin/sh 是否是 bash 脚本的好方法。所以我认为 weberjn 的答案并没有超出范围。