【问题标题】:What is the preferred Bash shebang?首选的 Bash shebang 是什么?
【发布时间】:2012-05-09 17:04:18
【问题描述】:

有没有Bashshebang 在大多数用途上客观上比其他人更好?

  • #!/usr/bin/env bash
  • #!/bin/bash
  • #!/bin/sh
  • #!/bin/sh -

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

【问题讨论】:

  • 以及它在 OpenBSD 上的 /usr/local/bin/bash
  • 添加破折号是为了防止某种 setuid root 欺骗攻击,请参阅security.stackexchange.com/questions/45490/…
  • 我会赞成这个,但它的分数是 1337,我不想打扰它!

标签: bash shebang


【解决方案1】:

您应该使用 #!/usr/bin/env bash 代替 portability:不同的 *nixes 将 bash 放在不同的位置,使用 /usr/bin/env 是运行第一个 bash 的解决方法PATH。还有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 更多的机器上,因此以该行开头的脚本将在尽可能多的机器上执行预期的操作。
【解决方案2】:

我推荐使用:

#!/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的特殊处理。

【讨论】:

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

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

另请注意,当被唤起为shbash 在某种程度上behaves as POSIX standard sh(另请参阅the GNU docs 关于此)。

【讨论】:

  • 公共域 Korn Shell (pdksh) 是 OpenBSD 的默认设置。
  • 大多数系统不会/bin/sh链接到/usr中的任何位置,因为这会使初始化脚本在/usr挂载之前很难运行。
  • @aij 我不知道为什么我把“许多或大多数”放在那里——我是一个 Fedora 用户,其中 /bin/sbin 多年来一直是默认的符号链接,到/usr/bin/usr/sbin,所以在这种情况下/bin/sh 是到bash 的链接,而实际目录是/usr/bin。但我会更正上述内容。
【解决方案4】:

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

#!/bin/sh -

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

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

#!/usr/bin/env bash

或任何语言,例如 Perl

#!/usr/bin/env perl

请务必查看man 页面中的bash

man bash

env:

man env

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

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

【讨论】:

    【解决方案5】:

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

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

    【讨论】:

    • Bash 没有安装在 OpenBSD 上。如果您通过pkg_add 安装它,则它位于/usr/local/bin,可能不在路径上。
    • POSIX 功能怎么样?
    【解决方案6】:

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

    【讨论】:

      【解决方案7】:

      #!/bin/sh

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

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

      【讨论】:

      • 但问题是 Bash 脚本具体使用什么。这有一个明显且潜在的严重缺点,即它不适用于 Bash 脚本(即任何使用 Bash-only 功能的东西)。对于新手来说,这是一个常见的陷阱。另见Difference between sh and bash
      猜你喜欢
      • 2013-12-28
      • 2011-12-12
      • 2013-09-30
      • 2019-11-28
      • 2019-04-06
      • 2019-09-11
      • 2011-12-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多