在shebang中使用#!/ usr / bin / env或#!/ bin / env的区别是什么?

时间:2011-04-05 08:15:40

标签: bash env

会有任何差异,还是个人选择?

4 个答案:

答案 0 :(得分: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将无效。

答案 1 :(得分:2)

米克尔的解释很棒,它错过了一个小事实(这很重要),它只传递了一个包含所有空格的参数:

#!<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"

哪个不起作用。

答案 2 :(得分:1)

/usr/bin/env是指向/bin/env的软链接。基本上,您使用的是/bin/env

答案 3 :(得分:0)

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

  • /文件系统在启动初期安装。
  • /usr 可能已在以后挂载,可能正在运行/中的脚本和程序来安排挂载。示例:某些站点通过从网络挂载/ usr来节省空间,但是您需要首先进入网络。例如:这是一个很大的本地文件系统,但是如果它受到损坏,则需要fsck之类的工具来尝试对其进行修复。

因此/bin/sbin(使用/lib)必须包含一个最小系统,该系统至少应包括/ bin / sh处的shell,并且必须编写类似/bin/echo的脚本,/bin/test等系统工具,例如/bin/mount/sbin/mount/bin/fsck ...

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

  • 在/ usr / bin /中,但不在/ bin
  • 在/ bin中,但不在/ usr / bin
  • 两者都与symlink相同
  • 两者都不同!例如。某些系统使用/bin/sh作为最小的外壳程序(例如dash)来加快启动速度,但是将/usr/bin/sh-> /usr/bin/bash进行符号链接(iirc,以“ sh”的形式调用bash进入posix模式,但仍然是另一个功能更强大的shell)。

因此,使用env编写可移植脚本的技巧-env恰好进行了PATH查找。 (它在其他不进行PATH查找的地方也很有用,例如docker exec。)

发生了什么变化

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

/ usr统一

现在,//usr可能失去了目标。原则上,每个人都可以同时使用一个文件系统和符号链接,尽管某些特定的设置可能会中断并且必须更改...

有关“ / usr统一”思想的概述,请参见2012年的https://lwn.net/Articles/483921/。例如Fedora完成了它:https://fedoraproject.org/wiki/Features/UsrMove。许多其他发行版都没有,或者仍在辩论中,或者正在淘汰某些发行版以减少用户数量。例如,请参见debian的准备工作:https://wiki.debian.org/UsrMerge