在Bash脚本的头中,这两个语句之间有什么区别:
>
#!/usr/bin/envbash
#/usr/bin/bash
当我查阅
env
手册页时,我得到了以下定义:
env - run a program in a modified environment
这是什么意思?
如果shell脚本以#开头/bin/bash
,它们将始终与/bin
中的bash
一起运行。但是,如果它们以#开头/usr/bin/env bash
,他们将在$PATH
中搜索bash
,然后从他们能找到的第一个开始。
为什么这会有用?假设您想要运行需要bash4的bash
脚本。x或更高版本,但您的系统只有bash
3。已安装x,但当前您的发行版不提供更新版本,或者您不是管理员,无法更改该系统上安装的内容。
当然,您可以下载bash源代码并从头开始构建自己的bash,例如将其放置到~/bin
。您还可以在中修改
文件以包含$PATH
变量。bash_profile~/bin
作为第一个条目(PATH=$HOME/bin:$PATH
as~
不会在$PATH
中展开)。如果现在调用bash
,shell将首先按顺序在$PATH
中查找它,因此它以~/bin
开头,在那里它将找到您的bash
。如果脚本使用#搜索
,因此这些脚本现在可以使用自定义的bash
,也会发生同样的情况/usr/bin/env bashbash
构建在您的系统上运行。
一个缺点是,这可能会导致意想不到的行为,例如,在同一台机器上运行相同的脚本可能会使用不同的解释器为不同的环境或具有不同搜索路径的用户运行,从而导致各种头痛。
env
的最大缺点是,某些系统只允许一个参数,因此不能执行此操作/usr/bin/env
它甚至可能有安全隐患,例如,如果未将sudo
配置为清理环境,或者$PATH
被排除在清理之外。让我示范一下:
通常/bin
是一个保护良好的地方,只有root
能够更改那里的任何内容。但是,主目录不是您运行的任何程序都可以对其进行更改的。这意味着恶意代码可能会将一个假的bash
放入某个隐藏目录,修改您的。bash_profile
将该目录包括在$PATH
中,因此所有脚本都使用#/usr/bin/env bash
将以该伪bash结束运行。如果sudo
保留$PATH
,您就有大麻烦了。
例如,考虑一个工具创建一个文件~/. vil/bash
,内容如下:
#!/bin/bash
if [ $EUID -eq 0 ]; then
echo "All your base are belong to us..."
# We are root - do whatever you want to do
fi
/bin/bash "$@"
让我们制作一个简单的脚本示例。上海
:
#!/usr/bin/env bash
echo "Hello World"
概念证明(在sudo
保存$PATH
的系统上):
$ ./sample.sh
Hello World
$ sudo ./sample.sh
Hello World
$ export PATH="$HOME/.evil:$PATH"
$ ./sample.sh
Hello World
$ sudo ./sample.sh
All your base are belong to us...
Hello World
通常,经典shell都应该位于/bin
中,如果出于任何原因不想将它们放在那里,那么在/bin
中放置一个指向它们真实位置的符号链接(或者可能/bin
本身就是一个符号链接)并不是一个问题,所以我总是选择\/bin/sh
和#/bin/bash
。如果这些都不起作用的话,会有太多的东西坏掉。并不是POSIX需要这些位置(POSIX没有标准化路径名,因此它甚至没有标准化shebang特性),而是它们非常常见,即使系统不提供/bin/sh
,它也可能理解#/bin/sh
并知道如何使用它,可能只是为了与现有代码兼容。
但是对于更现代的、非标准的可选解释器,如Perl、PHP、Python或Ruby,它并没有真正指定它们应该位于的任何地方。它们可能在/usr/bin
中,但也可能在/usr/local/bin
中,或者在完全不同的层次分支中(/ap/...
,/应用程序/...
,等等)。这就是为什么这些经常使用#!/usr/bin/envxxx
的语法。
使用#/usr/bin/env NAME
使shell在$PATH环境变量中搜索名称的第一个匹配项。如果您不知道绝对路径或不想搜索它,那么它可能很有用。
通过/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脚本,而不必重新编写可执行行)。但在安全性是重点的情况下,后者将是首选,因为它限制了代码注入的可能性。
问题内容: 在Bash脚本的标头中,这两个语句之间有什么区别: 当查阅 手册页时,得到以下定义: 这是什么意思? 问题答案: 运行命令,通过具有寻找不管程序的默认版本是在当前的利益 ENV ironment。 这样,您不必在系统上的特定位置查找它,因为这些路径可能在不同系统上的不同位置。只要它在您的路径中,它就会找到它。 缺点是,如果您希望支持Linux,则将无法传递多个参数(例如,您将无法编写)
我在许多地方看到过,包括本网站上的建议(首选的Bash shebang是什么?),使用而不是。我甚至看到一个有进取心的人建议使用是错误的,这样做会丢失bash功能。 尽管如此,我在一个严格控制的测试环境中使用bash,在这个环境中,循环中的每个驱动器本质上都是单个主驱动器的克隆。我理解可移植性的论点,尽管它不一定适用于我的情况。是否还有其他理由选择而不是替代方案?假设考虑可移植性,是否有理由使用它
本文向大家介绍bash: /usr/bin/autocrorder: /usr/bin/python^M: bad interpreter: No such file or directory,包括了bash: /usr/bin/autocrorder: /usr/bin/python^M: bad interpreter: No such file or directory的使用技巧和注意事项,
问题内容: 我正在尝试编译我的程序,它返回此错误: 在我的makefile文件中,我使用命令并链接到我的库,这是到我的库的另一个目录的符号链接。 是否可以添加选项以使其正常工作? 问题答案: 如果您的图书馆名称是say 并且位于路径上,请说: 然后将其链接到您的程序:
问题内容: 我正在尝试使用Python 2.7安装MySQLdb。我收到的错误如下所示: 显然,它找不到Python 2.7。展望我看到: 该符号是什么意思?谁能建议对此错误采取补救措施? 问题答案: 它找不到Python库,而不是可执行文件。运行以查看Python库的位置,然后将其添加到库路径(例如,如果位于中,则要调用)。 该符号意味着该文件是一个符号链接; 表示它是可执行文件(这些文件由产生
因此,我试图使用make-f Makefile编译一个程序,但我得到了以下错误/usr/bin/ld:not find-lgd 生成文件: 替换(libgd.a libgd.la libgd.so libgd.so.2 libgd.so.2.0.0)后,我收到以下错误: