我在很多地方,包括这个网站上的推荐(首选的Bash shebang是什么?),看到使用#!/usr/bin/env bash优先于#!/bin/bash我甚至看到一个有进取心的人建议使用#!/bin/bash是错误的,这样做会丢失bash功能。

尽管如此,我在一个严格控制的测试环境中使用bash,其中流通的每个驱动器本质上都是单个主驱动器的克隆。我理解便携性的观点,尽管它并不一定适用于我的情况。还有其他原因让我更喜欢#!/usr/bin/env bashover替代方案,假设可移植性是一个问题,有任何理由使用它会破坏功能吗?


当前回答

bash的标准位置是/bin,我怀疑在所有系统上都是如此。但是,如果您不喜欢这个版本的bash呢?例如,我想使用bash 4.2,但我的Mac上的bash是3.2.5。

我可以尝试在/bin中重新安装bash,但这可能是一个坏主意。如果我更新我的操作系统,它将被覆盖。

但是,我可以在/usr/local/bin/bash中安装bash,并将我的PATH设置为:

PATH="/usr/local/bin:/bin:/usr/bin:$HOME/bin"

现在,如果我指定bash,我就不会在/bin/bash中得到旧的、粗糙的代码,而是在/usr/local/bin中得到更新的、漂亮的代码。好了!

除了我的shell脚本有这个!因此,当我运行shell脚本时,我得到的是旧而糟糕的bash版本,它甚至没有关联数组。

使用/usr/bin/env bash将使用在我的PATH中找到的bash版本。如果我设置我的PATH,那么执行/usr/local/bin/bash,这就是我的脚本将使用的bash。

在bash中很少看到这种情况,但在Perl和Python中更常见:

Certain Unix/Linux releases which focus on stability are sometimes way behind with the release of these two scripting languages. Not long ago, RHEL's Perl was at 5.8.8 -- an eight year old version of Perl! If someone wanted to use more modern features, you had to install your own version. Programs like Perlbrew and Pythonbrew allow you to install multiple versions of these languages. They depend upon scripts that manipulate your PATH to get the version you want. Hard coding the path means I can't run my script under brew. It wasn't that long ago (okay, it was long ago) that Perl and Python were not standard packages included in most Unix systems. That meant you didn't know where these two programs were installed. Was it under /bin? /usr/bin? /opt/bin? Who knows? Using #! /usr/bin/env perl meant I didn't have to know.

为什么你不应该使用#!/usr/bin/env bash

When the path is hardcoded in the shebang, I have to run with that interpreter. Thus, #! /bin/bash forces me to use the default installed version of bash. Since bash features are very stable (try running a 2.x version of a Python script under Python 3.x) it's very unlikely that my particular BASH script will not work, and since my bash script is probably used by this system and other systems, using a non-standard version of bash may have undesired effects. It is very likely I want to make sure that the stable standard version of bash is used with my shell script. Thus, I probably want to hard code the path in my shebang.

其他回答

有很多系统在/bin中没有Bash,比如FreeBSD和OpenBSD。如果你的脚本想要移植到许多不同的unix,你可能需要使用#!/usr/bin/env bash代替#!/bin/bash。

注意,这并不适用于sh;对于兼容bourne的脚本,我只使用#!/bin/sh,因为我认为几乎所有的Unix都在/bin中有sh。

对于调用bash来说,这有点过头了。除非您在~/bin中有多个bash二进制文件,但这也意味着您的代码依赖于$PATH中有正确的内容。

不过,它对于python之类的东西很方便。有一些包装器脚本和环境会导致使用其他的python二进制文件。

但是使用二进制文件的确切路径不会丢失任何东西,只要您确定它是您真正想要的二进制文件。

# !/usr/bin/env在PATH中搜索bash,而bash并不总是在/bin中,特别是在非linux系统中。例如,在我的OpenBSD系统上,它位于/usr/local/bin中,因为它是作为可选包安装的。

如果您绝对确定bash在/bin中,并且将一直在/bin中,那么将它直接放在shebang中也没有什么害处——但是我建议不要这样做,因为脚本和程序都有超出我们最初认为的生命周期。

 #!/usr/bin/env bash

肯定更好,因为它从系统环境变量中找到bash可执行路径。

转到Linux shell并键入

env

它将打印所有环境变量。

转到shell脚本并键入

echo $BASH

它将打印您的bash路径(根据环境变量列表),您应该使用该路径在脚本中构建正确的shebang路径。

bash的标准位置是/bin,我怀疑在所有系统上都是如此。但是,如果您不喜欢这个版本的bash呢?例如,我想使用bash 4.2,但我的Mac上的bash是3.2.5。

我可以尝试在/bin中重新安装bash,但这可能是一个坏主意。如果我更新我的操作系统,它将被覆盖。

但是,我可以在/usr/local/bin/bash中安装bash,并将我的PATH设置为:

PATH="/usr/local/bin:/bin:/usr/bin:$HOME/bin"

现在,如果我指定bash,我就不会在/bin/bash中得到旧的、粗糙的代码,而是在/usr/local/bin中得到更新的、漂亮的代码。好了!

除了我的shell脚本有这个!因此,当我运行shell脚本时,我得到的是旧而糟糕的bash版本,它甚至没有关联数组。

使用/usr/bin/env bash将使用在我的PATH中找到的bash版本。如果我设置我的PATH,那么执行/usr/local/bin/bash,这就是我的脚本将使用的bash。

在bash中很少看到这种情况,但在Perl和Python中更常见:

Certain Unix/Linux releases which focus on stability are sometimes way behind with the release of these two scripting languages. Not long ago, RHEL's Perl was at 5.8.8 -- an eight year old version of Perl! If someone wanted to use more modern features, you had to install your own version. Programs like Perlbrew and Pythonbrew allow you to install multiple versions of these languages. They depend upon scripts that manipulate your PATH to get the version you want. Hard coding the path means I can't run my script under brew. It wasn't that long ago (okay, it was long ago) that Perl and Python were not standard packages included in most Unix systems. That meant you didn't know where these two programs were installed. Was it under /bin? /usr/bin? /opt/bin? Who knows? Using #! /usr/bin/env perl meant I didn't have to know.

为什么你不应该使用#!/usr/bin/env bash

When the path is hardcoded in the shebang, I have to run with that interpreter. Thus, #! /bin/bash forces me to use the default installed version of bash. Since bash features are very stable (try running a 2.x version of a Python script under Python 3.x) it's very unlikely that my particular BASH script will not work, and since my bash script is probably used by this system and other systems, using a non-standard version of bash may have undesired effects. It is very likely I want to make sure that the stable standard version of bash is used with my shell script. Thus, I probably want to hard code the path in my shebang.