bash 在shebang 中使用#!/usr/bin/env 或#!/bin/env 有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5549044/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What's the difference of using #!/usr/bin/env or #!/bin/env in shebang?
提问by Cheng
Will there be any difference or it's just a personal choice?
会有什么区别还是只是个人选择?
采纳答案by Mikel
#!<interpreter> <arguments>tries to run <interpreter> <arguments>to read and run the rest of the file.
#!<interpreter> <arguments>尝试运行<interpreter> <arguments>以读取并运行文件的其余部分。
So #!/usr/bin/envmeans that there must be a program called /usr/bin/env;#!/bin/envmeans that there must be a program called /bin/env.
所以#!/usr/bin/env意味着必须有一个程序叫做/usr/bin/env; #!/bin/env意味着必须有一个名为 的程序/bin/env。
Some systems have one and not the other.
有些系统只有一个,没有另一个。
In my experience, most have /usr/bin/env, so #!/usr/bin/envis more common.
根据我的经验,大多数都有/usr/bin/env,所以#!/usr/bin/env更常见。
Unix systems will try to run <interpreter>using execve, which is why it must be a full path, and #!envwithout a path will not work.
Unix 系统会尝试<interpreter>使用 using运行execve,这就是为什么它必须是完整路径,#!env没有路径将不起作用。
回答by estani
Mikel explanation is great, it misses just a small fact (which is rather important), it's only one argument being passed including all spaces:
Mikel 的解释很棒,它忽略了一个小事实(这很重要),它只传递了一个参数,包括所有空格:
#!<Interpreter> <argument>
Results in calling:
调用结果:
$ <Interpreter> '<argument>' path_to_calling_script
So for Example:
所以例如:
$ cat /tmp/test
#!/usr/bin/env python
print "hi"
$ /tmp/test
is the same as calling:
与调用相同:
$ /usr/bin/env "python" /tmp/test
The quotes try to show that if you add any flag or other values will be part of the argument being called.
引号试图表明如果您添加任何标志或其他值将成为被调用参数的一部分。
#!/bin/bash -c /bin/env python
Will be interpreted as:
将被解释为:
$ /bin/bash "-c /bin/env python"
Which won't work.
这行不通。
回答by Beni Cherniavsky-Paskin
Historically, UNIX had 2 bunches of binaries:
历史上,UNIX 有 2 束二进制文件:
/filesystem mounted early on boot./usrmighthave been mounted later, possibly running scripts and programs from/to arrange the mount. Example: some sites saved space by mounting /usr from network, but you need to get on the network first. Example: it's a large local filesystem, but if it gets damaged, you want tools likefsckto try fixing it.
/文件系统在启动时提前挂载。/usr可能稍后安装,可能会运行脚本和程序/来安排安装。示例:有些站点通过从网络挂载 /usr 来节省空间,但您需要先上网络。示例:它是一个大型本地文件系统,但如果它被损坏,您需要类似的工具fsck来尝试修复它。
Thus, /binand /sbin(using /lib), had to contain a minimal system including at least a shell at /bin/sh, scripting essentials like /bin/echo, /bin/testetc., system tools like /bin/mountor /sbin/mount, and /bin/fsck...
因此,/bin和/sbin(使用/lib),必须包含一个最小系统,至少包括 /bin/sh 中的一个 shell、脚本基本要素(如/bin/echo)/bin/test、系统工具(如/bin/mount或/sbin/mount)和/bin/fsck...
Thus in different unixes, almost any program might have been:
因此,在不同的 Unix 中,几乎任何程序都可能是:
- in /usr/bin/ but NOT /bin
- in /bin but NOT /usr/bin
- in both, same as symlink
- in both but different! E.g. some systems played with
/bin/shbeing a very minimal shell (e.g.dash) for faster startup, but symlinking/usr/bin/sh->/usr/bin/bash(iirc, invoking bash as "sh" puts it into some posix mode, but it's still a different more powerful shell).
- 在 /usr/bin/ 但不是 /bin
- 在 /bin 但不是 /usr/bin
- 在两者中,与符号链接相同
- 在两者但不同!例如,某些系统使用
/bin/sh非常小的 shell(例如dash)来加快启动速度,但是符号链接/usr/bin/sh->/usr/bin/bash(iirc,将 bash 调用为“sh”使其进入某种 posix 模式,但它仍然是一个不同的更强大的 shell)。
Thus the trick of using envto write portable scripts — envjust happens to do a PATH lookup. (It's also useful in other places that don't do PATH lookups, e.g. docker exec.)
因此,使用env编写可移植脚本的技巧——env恰好是进行 PATH 查找。(它在其他不进行 PATH 查找的地方也很有用,例如docker exec。)
What changed
改变了什么
These were valid use cases but modern Linux followed a similar argument of "need small userspace to mount / recover main userspace" for /itself too! The pivot syscall and initrdwere introduced, and tooling grew to copy the parts you need into it.
这些都是有效的用例,但现代 Linux 也遵循类似的论点,即“需要小用户空间来挂载/恢复主用户空间” /! 引入了枢轴系统调用 和initrd,并且工具增长以将您需要的部分复制到其中。
/usr unification
/usr 统一
Now, /vs /usrarguably lost its purpose. Having both on one filesystem and symlinking was doable for everybody in principle, though some particular setups would break and would have to change...
现在,/vs/usr可以说失去了它的目的。原则上,在一个文件系统上同时使用符号链接对每个人都是可行的,尽管某些特定设置会中断并且必须更改...
See https://lwn.net/Articles/483921/from 2012 for overview of this "/usr unification" idea. For example Fedora completed it: https://fedoraproject.org/wiki/Features/UsrMove. Many other distros haven't, or are still debating it, or ironing out some kinds to break less users. For example see debian's preparation: https://wiki.debian.org/UsrMerge.
从 2012 年开始,请参阅https://lwn.net/Articles/483921/以了解此“/usr 统一”想法的概述。例如 Fedora 完成了它:https://fedoraproject.org/wiki/Features/UsrMove。许多其他发行版还没有,或者仍在争论它,或者解决一些问题以减少用户。例如查看 debian 的准备工作:https: //wiki.debian.org/UsrMerge。
回答by kurumi
/usr/bin/envis a soft link to /bin/env. Essentially, you are using /bin/env
/usr/bin/env是一个软链接/bin/env。基本上,您正在使用/bin/env

