是否可能有一个shebang,而不是指定解释程序的路径,而是使用解释程序的名称,然后让shell通过$ PATH找到它?
如果没有,为什么?
是否可能有一个shebang,而不是指定解释程序的路径,而是使用解释程序的名称,然后让shell通过$ PATH找到它?
如果没有,为什么?
Answers:
PATH查找是用户空间中标准C库的功能,通常环境变量也是如此。内核看不到环境变量,除非它在环境中从调用者传递execve
到新进程。
内核不会对路径execve
(取决于包装函数,例如execvp
执行PATH查找)或在Shebang中(其或多或少在execve
内部重新路由调用)的路径进行任何解释。因此,您需要将绝对路径放到shebang¹中。在最初的家当实施只是的几行代码,到现在也没有得到显著因为扩大。
在Unix的第一个版本中,当外壳程序发现您正在调用脚本时,它会自行进行调用。Shebang被添加到内核中有几个原因(总结了Dennis Ritchie的基本原理:
无路径shebang可能需要扩展内核以访问环境变量和进程PATH
,或者要求内核执行执行PATH查找的用户空间程序。第一种方法需要给内核增加不成比例的复杂性。第二种方法已经可以通过#!/usr/bin/env
射棒实现。
¹ 如果放置相对路径,则相对路径将相对于进程的当前目录(而不是包含脚本的目录)进行解释,这在shebang中几乎没有用。
execve
在shebang 中也不需要在shebang中使用绝对路径,尽管在shebang中具有相对路径没有多大意义。
/lib64/ld-linux-x86-64.so.2
(请参见ldd
输出)。Linux使它变得完全通用:binfmt
支持(自2.1.43版本开始)使您可以注册解释器路径/ magic-number-or-file-extension对。你可以有PE32 .exe
小号调用wine
,当你运行它们,Java类和JAR文件调用java
,等等,等等
发生的事情比目光所及。#!
行由Unix或Linux内核解释,#!
不是shell的一个方面。这意味着PATH
在内核决定执行什么时,它实际上并不存在。
解决不知道要运行或以perl
便携式方式或类似方式调用的可执行文件的最常见方法是使用#!/usr/bin/env perl
。内核执行/usr/bin/env
,它继承了一个PATH
环境变量。env
寻找(在这个例子中)perl
中PATH
,并使用execve(2)
系统调用来获得内核运行的perl
可执行文件。
$ strace sleep 1
execve("/usr/bin/sleep", ["sleep", "1"], [/* 99 vars */]) = 0
到完整路径的转换是由外壳程序完成的(更通用:在用户空间中)。内核期望它可以直接访问的文件名/路径。
如果希望系统通过查看PATH变量来找到可执行文件,则可以将shebang重写为#!/usr/bin/env EXEC
。
但是在这种情况下,搜索也不是内核。
strace
(转换为/usr/bin/strace
某个时刻)时带有2个参数。