我在很多地方,包括这个网站上的推荐(首选的Bash shebang是什么?),看到使用#!/usr/bin/env bash优先于#!/bin/bash我甚至看到一个有进取心的人建议使用#!/bin/bash是错误的,这样做会丢失bash功能。
尽管如此,我在一个严格控制的测试环境中使用bash,其中流通的每个驱动器本质上都是单个主驱动器的克隆。我理解便携性的观点,尽管它并不一定适用于我的情况。还有其他原因让我更喜欢#!/usr/bin/env bashover替代方案,假设可移植性是一个问题,有任何理由使用它会破坏功能吗?
通常# !Path /to/命令将触发bash在执行时将命令路径前置到调用脚本。的例子,
# file.sh
#!/usr/bin/bash
echo hi
./file.sh将启动一个新的进程,脚本将像/bin/bash ./file.sh一样执行
Now
# file.sh
#!/usr/bin/env bash
echo hi
将被执行为/usr/bin/env bash ./file.sh,引用env手册页将其描述为:
环境-在修改过的环境中运行程序
因此,env将在其PATH环境变量中查找bash命令,并在单独的环境中执行,其中环境值可以传递给env,如NAME=VALUE对。
你可以使用python等不同的解释器来测试其他脚本。
#!/usr/bin/env python
# python commands
你的问题是有偏见的,因为它假设#!/usr/bin/env bash优于#!/bin/bash。这种假设是不正确的,原因如下:
Env在两种情况下是有用的:
当解释器的多个版本不兼容时。
例如python 2/3, perl 4/5,或php 5/7
当位置依赖于PATH时,例如在python虚拟环境中。
但bash不属于这两种情况,因为:
bash非常稳定,特别是在Linux和BSD等现代系统上,它们构成了bash安装的绝大多数。
在/bin下通常只安装了一个版本的bash。
在过去的20多年里一直是这样,只有非常老的公寓(没有人再使用了)有一个不同的位置。
因此,通过/usr/bin/env遍历PATH变量对bash没有用处。
再加上这三个使用#!/bin/bash:
for system scripts (when not using sh) for which the PATH variable may not contain /bin.
For example cron defaults to a very strict PATH of /usr/bin:/bin which is fine, sure, but other context/environments may not include /bin for some peculiar reason.
when the user screwed-up his PATH, which is very common with beginners.
for security when for example you're calling a suid program that invokes a bash script. You don't want the interpreter to be found via the PATH variable which is entirely under the user's control!
最后,有人可能会争辩说,env生成bash有一个合理的用例:当需要使用#!/usr/bin/env -S VAR=value bash。
但这不是bash的问题,因为当您控制了shebang时,您也控制了整个脚本,所以只需在脚本中添加VAR=value,从而避免了前面提到的env在bash脚本中引入的问题。