在Bash脚本的头文件中,这两个语句的区别是什么:

#!/usr/bin/env bash #!/usr/bin/bash

当我查阅env手册页时,我得到了这样的定义:

 env - run a program in a modified environment

这是什么意思?


当前回答

通过/usr/bin/env运行命令的好处是查找当前环境中程序的默认版本。

这样,您就不必在系统上的特定位置查找它,因为这些路径可能位于不同系统上的不同位置。只要它在你的路上,它就会找到它。

一个缺点是,如果您希望支持Linux,您将无法传递多个参数(例如,您将无法编写/usr/bin/env awk -f),因为POSIX对如何解释行是模糊的,而Linux解释第一个空格之后的所有内容以表示单个参数。你可以在某些版本的env上使用/usr/bin/env -S来解决这个问题,但是这样脚本就会变得更不容易移植,并且会在最近的系统上崩溃(例如,即使是Ubuntu 16.04,如果不是更高的版本)。

另一个缺点是,由于您没有调用显式可执行文件,因此有可能出现错误和多用户系统安全问题(例如,如果有人设法在您的路径中获取名为bash的可执行文件)。

#!/usr/bin/env bash #lends you some flexibility on different systems
#!/usr/bin/bash     #gives you explicit control on a given system of what executable is called

在某些情况下,前者可能是首选(比如使用多个版本的python运行python脚本,而不必重写可执行行)。但是在安全性是重点的情况下,后者将是首选,因为它限制了代码注入的可能性。

其他回答

通过/usr/bin/env运行命令的好处是查找当前环境中程序的默认版本。

这样,您就不必在系统上的特定位置查找它,因为这些路径可能位于不同系统上的不同位置。只要它在你的路上,它就会找到它。

一个缺点是,如果您希望支持Linux,您将无法传递多个参数(例如,您将无法编写/usr/bin/env awk -f),因为POSIX对如何解释行是模糊的,而Linux解释第一个空格之后的所有内容以表示单个参数。你可以在某些版本的env上使用/usr/bin/env -S来解决这个问题,但是这样脚本就会变得更不容易移植,并且会在最近的系统上崩溃(例如,即使是Ubuntu 16.04,如果不是更高的版本)。

另一个缺点是,由于您没有调用显式可执行文件,因此有可能出现错误和多用户系统安全问题(例如,如果有人设法在您的路径中获取名为bash的可执行文件)。

#!/usr/bin/env bash #lends you some flexibility on different systems
#!/usr/bin/bash     #gives you explicit control on a given system of what executable is called

在某些情况下,前者可能是首选(比如使用多个版本的python运行python脚本,而不必重写可执行行)。但是在安全性是重点的情况下,后者将是首选,因为它限制了代码注入的可能性。

使用# !/usr/bin/env NAME使shell搜索$PATH环境变量中NAME的第一个匹配项。如果您不知道绝对路径或不想搜索它,它会很有用。

我发现它很有用,因为当我不知道env的时候,在我开始写脚本之前,我是这样做的:

type nodejs > scriptname.js #or any other environment

然后我将文件中的这一行修改为shebang。 我这样做是因为我不总是记得nodejs在我的计算机上的位置- /usr/bin/或/bin/,所以对我来说env非常有用。也许这里面有细节,但这就是我的理由

通过使用env命令而不是显式地将解释器的路径定义为/usr/bin/bash/,解释器将从第一次找到它的地方搜索并启动。这既有好处也有坏处

一个原因是它可以在Linux和BSD之间移植。