Mik*_*kel 14

#!<interpreter> <arguments>尝试运行<interpreter> <arguments>以读取并运行文件的其余部分.

所以#!/usr/bin/env意味着必须有一个叫做的程序/usr/bin/env;
#!/bin/env意味着必须有一个名为的程序/bin/env.

有些系统有一个而另一个没有.

根据我的经验,大多数人都有/usr/bin/env,所以#!/usr/bin/env更常见.

Unix系统将尝试<interpreter>使用execve,这就是为什么它必须是一个完整的路径,#!env没有路径将无法工作.

  • 特别地,OS/X具有`/ usr/bin/env`并且没有从`/ bin/env`到`/ usr/bin/env`的符号链接.你会得到一个`-bash:./ your_commnd:/ bin/env:错误的解释器:没有这样的文件或目录`错误. (3认同)

Ben*_*kin 7

从历史上看,UNIX 有 2 组二进制文件:

\n
    \n
  • /文件系统在启动时早期安装。
  • \n
  • /usr 可能稍后安装,可能运行脚本和程序来/安排安装。示例:有些站点通过从网络挂载 /usr 来节省空间,但您需要先连接网络。示例:它是一个大型本地文件系统,但如果它被损坏,您需要诸如fsck尝试修复它之类的工具。
  • \n
\n

因此,/bin并且/sbin(使用/lib)必须包含一个最小的系统,其中至少包括位于 /bin/sh 的 shell、脚本必需品(例如/bin/echo/bin/test)、系统工具(例如/bin/mount/sbin/mount)、以及/sbin/fsck...

\n

因此,在不同的 UNIX 中,几乎所有程序都可能是:

\n
    \n
  • 在 /usr/bin/ 但不是 /bin
  • \n
  • 在 /bin 但不是 /usr/bin
  • \n
  • 在两者中,与符号链接相同
  • \n
  • 两者都有但又不同!例如,某些系统使用/bin/sh一个非常小的 shell(例如dash)来加快启动速度,但符号链接/usr/bin/sh-> /usr/bin/bash(iirc,调用 bash 作为“sh”将其置于某种 posix 模式,但它仍然是一个不同的更强大的 shell)。
  • \n
\n

大多数时候,只需设置 $PATH 来包含这两个区域。但某些上下文喜欢#!docker exec需要固定的完整路径。env因此,使用编写可移植脚本 \xe2\x80\x94的技巧env恰好是进行 PATH 查找。

\n

发生了什么变化

\n

这些都是有效的用例,但现代 Linux 本身也遵循类似的“需要小用户空间来安装/恢复主用户空间”的论点/引入了pivot 系统调用initrd,并且工具不断发展以将您需要的部分复制到其中。

\n

/usr 统一

\n

现在,/VS/usr可以说失去了它的目的。原则上,在一个文件系统上同时使用符号链接对每个人来说都是可行的,尽管某些特定的设置会被破坏并且必须更改......

\n

有关“/usr 统一”想法的概述,请参阅2012 年的https://lwn.net/Articles/483921/ 。例如 Fedora 完成了它: https: //fedoraproject.org/wiki/Features/UsrMove。许多其他发行版还没有,或者仍在争论,或者解决某些问题以减少用户流失。例如,请参阅 debian 的准备工作:https://wiki.debian.org/UsrMerge

\n

/usr/local/、~/.local/等地方

\n

需要 PATH 查找的原因还有很多:

\n
    \n
  • 并非所有 UNIX 都可以开箱即用地安装所有语言,或者它们打包的内容太旧了。因此,虽然像这样的东西env总是存在于 /bin 或 /usr/bin 或两者中,但人们可能只在 /usr/local 或您的主目录下有(或更喜欢)python 和其他解释器...
  • \n
  • 许多语言版本/库管理器都有一种在隔离环境中运行的方法,并且通常这样的环境是通过可执行的“shims”激活的。例如,Python“virtualenv”目录有一个 bin/python3 二进制文件;因此,当您将该 bin/ 目录添加到您的 PATH 中时,并且如果您运行执行此操作的脚本#!/usr/bin/env python3,那么您只需使用特定于该环境的模块即可。
  • \n
\n

回到问题,env自己使用什么完整路径?

\n

按照同样的逻辑,在具有不同 /usr 的系统中,env其本身可能从任一位置丢失,因此您无法编写 100.00% 可移植的#!行。
\n实际上,两者都可能有效。我没有统计数据,但在多年的实践中,我认为/usr/bin/env这是更常用的推荐形式(示例

\n