为什么#!/ usr / bin / env bash优于#!/ bin / bash?
我曾经在很多地方看到过,包括对这个网站的推荐( 什么是首选Bash shebang? ),使用#!/usr/bin/env bash
优先于#!/bin/bash
。 我甚至看到一个有进取心的人build议使用#!/bin/bash
是错误的,而bash的function会因此丢失。
所有这一切,我使用bash在一个严格控制的testing环境中,每个stream通驱动器基本上是一个主驱动器的克隆。 我理解可移植性的论点,虽然它不一定适用于我的情况。 有没有其他的理由更喜欢#!/usr/bin/env bash
的替代品,并假设便携性是一个问题,是否有任何理由使用它可能会破坏function?
#!/usr/bin/env
在bash
searchPATH
, bash
并不总是在/bin
,特别是在非Linux系统上。 例如,在我的OpenBSD系统上,它位于/usr/local/bin
,因为它是作为可选包安装的。
如果你完全确定bash
是在/bin
并且永远是这样的,那么将它直接放在你的文件中是没有什么坏处的,但是我build议不要这样做,因为脚本和程序都超出了我们最初相信的程度。
bash的标准位置是/bin
,我怀疑在所有系统上都是如此。 但是,如果你不喜欢那个版本的bash呢? 例如,我想使用bash 4.2,但是我的Mac上的bash是3.2.5。
我可以尝试在/bin
重新安装bash,但这可能是一个坏主意。 如果我更新我的操作系统,它将被覆盖。
但是,我可以在/usr/local/bin/bash
安装/usr/local/bin/bash
,并将PATH设置为:
PATH="/usr/local/bin:/bin:/usr/bin:$HOME/bin"
现在,如果我指定了bash
,我不会在/bin/bash
得到旧的cruddy,而是在/usr/local/bin
更新,更炫的。 太好了!
除了我的shell脚本有!# /bin/bash
shebang。 因此,当我运行我的shell脚本时,我得到了那个甚至没有关联数组的旧式bash版本。
使用/usr/bin/env bash
将使用在我的PATH中find的bash版本。 如果我设置我的path,以便执行/usr/local/bin/bash
,那是我的脚本将使用的bash。
用bash来看这是很less见的,但在Perl和Python中更常见:
- 某些专注于稳定性的 Unix / Linux版本有时候会随着这两种脚本语言的发布而落后。 不久前,RHEL的Perl版本是5.8.8 – 一个八年的Perl版本! 如果有人想要使用更多的现代function,你必须安装自己的版本。
- 像Perlbrew和Pythonbrew这样的程序允许你安装这些语言的多个版本。 他们依靠脚本来操纵你的PATH来获得你想要的版本。 硬编码path意味着我不能在brew下运行我的脚本。
- 不久之前(好吧,很久以前)Perl和Python不是大多数Unix系统中包含的标准软件包。 这意味着你不知道这两个程序的安装位置。 在
/bin
吗?/usr/bin
?/opt/bin
? 谁知道? 使用#! /usr/bin/env perl
#! /usr/bin/env perl
意味着我不必知道。
而现在为什么你不应该使用#! /usr/bin/env bash
#! /usr/bin/env bash
当path在shebang中硬编码时,我必须和解释器一起运行。 因此, #! /bin/bash
#! /bin/bash
强制我使用默认的安装版本的bash。 由于bash特性非常稳定(尝试在Python 3.x下运行Python脚本的2.x版本),所以我的特定BASH脚本不太可能工作,因为我的bash脚本可能被这个系统和其他系统,使用非标准版本的bash可能会产生不良影响。 这很可能是我想确保稳定的标准版本的bash与我的shell脚本一起使用。 因此,我可能想要硬编码我的shebangpath。
为了调用bash
这有点矫枉过正。 除非你有〜/ bin中的多个bash
二进制文件,但是这也意味着你的代码依赖于$ PATH,并且有正确的东西。
对于像python
这样的东西来说,它是非常方便的。 有包装脚本和环境,导致使用替代python
二进制文件。
但是,只要您确定它是您真正想要的二进制文件,就不会使用二进制文件的确切path。
有很多系统在/bin
,FreeBSD和OpenBSD中都没有Bash,仅举几例。 如果您的脚本可以移植到许多不同的Unices,那么您可以使用#!/usr/bin/env bash
而不是#!/bin/bash
。
请注意,这不适用于sh
; 对于Bourne兼容的脚本,我完全使用#!/bin/sh
,因为我认为现有的每个Unix都已经在/bin
。