【发布时间】:2011-07-29 18:35:32
【问题描述】:
会有什么不同还是只是个人选择?
【问题讨论】:
会有什么不同还是只是个人选择?
【问题讨论】:
#!<interpreter> <arguments> 尝试运行 <interpreter> <arguments> 以读取并运行文件的其余部分。
所以#!/usr/bin/env表示一定有一个叫/usr/bin/env的程序;#!/bin/env表示一定有一个叫/bin/env的程序。
有些系统有一个而没有另一个。
根据我的经验,大多数都有/usr/bin/env,所以#!/usr/bin/env 更常见。
Unix 系统会尝试使用execve 运行<interpreter>,这就是为什么它必须是完整路径,而没有路径的#!env 将不起作用。
【讨论】:
/bin/bash,因此建议使用 /usr/bin/env 以实现可移植性。此外,如果你想在 $PATH 中排列的不同目录中运行更新版本的 BASH,env 会尊重并使用它,而 /bin/bash 显然是硬编码的。
/usr/bin/env 并且没有从/bin/env 到/usr/bin/env 的符号链接。你会得到一个-bash: ./your_commnd: /bin/env: bad interpreter: No such file or directory 错误。
/ 文件系统在启动早期安装。/usr 可能 稍后被挂载,可能运行来自/ 的脚本和程序来安排挂载。示例:某些站点通过从网络挂载 /usr 来节省空间,但您需要先进入网络。示例:它是一个大型本地文件系统,但如果它被损坏,您需要像 fsck 这样的工具来尝试修复它。因此,/bin 和 /sbin(使用 /lib)必须包含一个最小系统,包括至少一个位于 /bin/sh 的 shell、脚本必需品,如 /bin/echo、/bin/test 等,系统/bin/mount 或 /sbin/mount 和 /sbin/fsck 等工具...
因此,在不同的 Unix 中,几乎任何程序都可能是:
/bin/sh 是一个非常小的shell(例如dash)以加快启动速度,但符号链接/usr/bin/sh -> /usr/bin/bash(iirc,将bash 调用为“sh”使其进入某种posix 模式,但它是仍然是一个不同的更强大的外壳)。大多数时候,只需将 $PATH 设置为包括这两个区域。但是像#! 或docker exec 这样的一些上下文需要一个固定的完整路径。因此,使用env 编写可移植脚本的技巧——env 恰好进行 PATH 查找。
这些都是有效的用例,但现代 Linux 也遵循了类似的论点,即 / 本身也需要小用户空间来挂载/恢复主用户空间! The pivot syscall and initrd 被引入,并且工具增长到将您需要的部分复制到其中。
现在,/ vs /usr 可以说失去了它的目的。在一个文件系统上同时使用符号链接对每个人原则上都是可行的,尽管某些特定设置会中断并且必须更改......
请参阅 2012 年的 https://lwn.net/Articles/483921/ 以了解此“/usr 统一”理念的概述。例如 Fedora 完成了它:https://fedoraproject.org/wiki/Features/UsrMove。许多其他发行版还没有,或者仍在争论它,或者解决一些问题以减少用户。例如看debian的准备:https://wiki.debian.org/UsrMerge。
还有更多需要 PATH 查找的理由:
env 这样的东西总是存在于 /bin 或 /usr/bin 或两者中,但可能只有(或更喜欢)python 和其他解释器位于 /usr/local 或您的主目录下......#!/usr/bin/env python3 的脚本,那么您只需要使用特定于该环境的模块即可。env 本身使用什么完整路径?按照相同的逻辑,在具有不同 /usr 的系统中,env 本身可能会从任一位置丢失,因此您无法编写 100.00% 可移植的 #! 行。
在实践中,两者都可能起作用。我没有统计数据,但多年来我一直将/usr/bin/env 视为更常用的推荐形式(example)?
【讨论】:
Mikel 的解释很棒,它忽略了一个小事实(这是相当重要的),它只是传递了一个包含所有空格的参数:
#!<Interpreter> <argument>
调用结果:
$ <Interpreter> '<argument>' path_to_calling_script
例如:
$ cat /tmp/test
#!/usr/bin/env python
print "hi"
$ /tmp/test
和调用一样:
$ /usr/bin/env "python" /tmp/test
引号试图表明,如果您添加任何标志或其他值将成为被调用参数的一部分。
#!/bin/bash -c /bin/env python
将被解释为:
$ /bin/bash "-c /bin/env python"
这行不通。
【讨论】:
/usr/bin/env 是指向/bin/env 的软链接。本质上,您使用的是/bin/env
【讨论】:
/bin/env 和 /usr/bin/env 是一个符号链接