为什么不使用无路径的 shebangs?

为什么不使用无路径的 shebangs?

是否可以有一个 shebang,它不指定解释器的路径,而是具有解释器的名称,并让 shell 通过 $PATH 找到它?

如果不是,有什么原因吗?

答案1

PATH 查找是用户空间中标准 C 库的一项功能,环境变量也是如此。内核看不到环境变量,除非它从调用者传递环境变量execve到新的流程。

内核不会对 in 中的路径execve(这取决于包装函数,例如execvp执行 PATH 查找)或 shebang 中的路径(或多或少地execve在内部重新路由调用)执行任何解释。因此,您需要将绝对路径放入 shebang 中。这原始 Shebang 实施只是几行代码,此后就没有显着扩展。

在 Unix 的第一个版本中,当 shell 注意到您正在调用脚本时,它会执行调用自身的工作。 Shebang被添加到内核中有几个原因(总结一下丹尼斯·里奇的基本原理:

  • 调用者不必担心要执行的程序是 shell 脚本还是本机二进制文件。
  • 脚本本身指定要使用的解释器,而不是调用者。
  • 内核使用日志中的脚本名称。

无路径 shebangs 需要增强内核以访问环境变量和进程PATH,或者让内核执行执行 PATH 查找的用户空间程序。第一种方法需要向内核添加不成比例的复杂性。第二种方法已经可以通过#!/usr/bin/env舍邦

1如果您输入相对路径,它将相对于进程的当前目录(而不是包含脚本的目录)进行解释,这在 shebang 中几乎没有用处。

答案2

发生的事情比表面上看到的还要多。#!行由 Unix 或 Linux 内核解释,#!不是 shell 的一个方面。这意味着PATH当内核决定执行什么时,它并不真正存在。

处理不知道要运行哪个可执行文件或以可移植方式或类似方式调用的最常见方法perl是使用#!/usr/bin/env perl.内核执行/usr/bin/env,它继承了一个PATH环境变量。env查找(在本示例中)perlPATH使用execve(2)系统调用来让内核运行perl可执行文件。

答案3

$ strace sleep 1
execve("/usr/bin/sleep", ["sleep", "1"], [/* 99 vars */]) = 0

到完整路径的转换由 shell 完成(更一般:在用户空间中)。内核需要一个可以直接访问的文件名/路径。

如果您希望系统通过查找 PATH 变量来找到您的可执行文件,您可以将 shebang 重写为#!/usr/bin/env EXEC.

但在这种情况下,也不是内核进行搜索。

相关内容