Linux 通过shebang线路链接口译员是否可移植?

Linux 通过shebang线路链接口译员是否可移植?,linux,shell,unix,posix,executable,Linux,Shell,Unix,Posix,Executable,在POSIX操作系统上,通过所谓的shebang行将脚本绑定到特定的解释器是一种众所周知的做法。例如,如果执行以下脚本(给定足够的文件系统权限),操作系统将启动/bin/sh解释器,并将脚本的文件名作为其第一个参数。随后,shell将执行脚本中的命令,跳过shebang行,并将其视为注释 #! /bin/sh date -R echo hello world 可能的产出: Sat,2017年4月1日12:34:56+0100 你好,世界 我过去认为解释器(/bin/sh在本例中)必须是本机

在POSIX操作系统上,通过所谓的shebang行将脚本绑定到特定的解释器是一种众所周知的做法。例如,如果执行以下脚本(给定足够的文件系统权限),操作系统将启动
/bin/sh
解释器,并将脚本的文件名作为其第一个参数。随后,shell将执行脚本中的命令,跳过shebang行,并将其视为注释

#! /bin/sh

date -R
echo hello world
可能的产出:

Sat,2017年4月1日12:34:56+0100
你好,世界
我过去认为解释器(
/bin/sh
在本例中)必须是本机可执行文件,而不能是脚本本身,而脚本本身又需要启动另一个解释器

然而,我还是继续做了下面的实验

使用以下保存为
/tmp/explorer.py
的哑shell

#/usr/bin/python3
导入系统
导入子流程
对于sys.argv[1:]中的脚本:
以打开(脚本)作为istr:
状态=任何(
地图(
subprocess.call,
地图(
斯普利特街,
滤器(
lambda s:s而不是s.startswith(“#”),
地图(str.strip,istr)
)
)
)
)
如果状态:
系统退出(状态)
…并将以下脚本另存为
/tmp/script.xyz

#! /tmp/interpreter.py

date -R
echo hello world
…我能够(在使这两个文件都可执行之后)执行
script.xyz

5gon12eder:/tmp> ls -l total 8 -rwxr-x--- 1 5gon12eder 5gon12eder 493 Jun 19 01:01 interpreter.py -rwxr-x--- 1 5gon12eder 5gon12eder 70 Jun 19 01:02 script.xyz 5gon12eder:/tmp> ./script.xyz Mon, 19 Jun 2017 01:07:19 +0200 hello world 5gon12eder:/tmp>ls-l 总数8 -rwxr-x---1 5gon12eder 5gon12eder 493 Jun 19 01:01解释器.py -rwxr-x---1 5gon12eder 5gon12eder 70 Jun 19 01:02 script.xyz 5gon12eder:/tmp>/script.xyz 2017年6月19日星期一01:07:19+0200 你好,世界 这让我很惊讶。我甚至可以通过另一个脚本启动
scrip.xyz

所以,我要问的是:

  • 我的实验观察到的行为是可移植的吗
  • 实验是否正确进行,或者是否存在不起作用的情况?不同的(类Unix)操作系统如何
  • 如果这是可行的,那么就调用而言,本机可执行文件和解释脚本之间是否没有明显的差异

类Unix操作系统中的新可执行文件由系统调用
execve
(2)启动。
execve
的手册页包括:

解释器脚本
解释器脚本是已执行的文本文件
已启用权限,且其第一行的格式为:
#! 解释器[可选参数]
解释器必须是可执行文件的有效路径名
它本身不是一个脚本。如果execve()的filename参数
指定解释器脚本,然后将调用解释器
有以下论点:
解释器[可选参数]文件名参数。。。
其中arg。。。是argv指向的一系列单词
execve()的参数。
对于便携使用,可选arg应该不存在,或者不存在
指定为单个单词(即,不应包含白色
空间);见下文注释。
因此,在这些限制(类似Unix,最多一个单词的可选参数)中,shebang脚本是可移植的。阅读手册页了解更多详细信息,包括二进制可执行文件和脚本之间调用的其他差异

  • 见下文黑体字:

    这种机制允许脚本在几乎任何上下文中使用 正常编译程序可以是,包括作为完整系统程序, 甚至作为其他脚本的翻译。不过,作为警告,有些 早期版本的内核支持限制了解释器的长度 指令,大约32个字符(第一个字符中只有16个字符 实现),将无法将解释器名称从任何 指令中的参数,或具有其他怪癖。此外,一些 现代系统允许对整个机构进行约束或调整 出于安全目的禁用(例如,设置用户id支持已禁用) 已在许多系统上禁用脚本)。——

  • 来自
    COLUMNS=75 man execve | grep-nA 23”的输出
    解释器脚本“| head-39
    在Ubuntu 17.04上, 特别是第186-189行,它告诉我们什么可以在Linux上工作(即脚本可以是解释器,最多四层):

  • 166:解释器脚本 167-解释器脚本是具有执行权限的文本文件 168-已启用,其第一行的形式为: 169- 170- #! 解释器[可选参数] 171- 172-解释器必须是可执行文件的有效路径名。 173-如果execve()的filename参数指定解释器 174-脚本,然后将使用以下参数调用解释器 175-附件: 176- 177-解释器[可选参数]文件名参数。。。 178- 179-在哪里arg。。。是argv argu指向的一系列单词 从argv[1]开始执行execve()的180个字符。 181- 182-对于便携式使用,可选arg应该不存在,或者 183-指定为单个单词(即不应包含白色 184-空间);见下文注释。 185- 186-自Linux2.6.28以来,内核允许脚本的解释器 187年的今天,它本身就是一个剧本。此权限是递归的,最多为 188-限制四个递归,以便解释器可以是脚本 189-由脚本解释,依此类推。 -- 343:解释器脚本 344-第一行允许的最大行长为127个字符 345-解释器脚本中的行。 346- 347-解释器的可选arg参数的语义 348-脚本在implem中有所不同 166: Interpreter scripts 167- An interpreter script is a text file that has execute permission 168- enabled and whose first line is of the form: 169- 170- #! interpreter [optional-arg] 171- 172- The interpreter must be a valid pathname for an executable file. 173- If the filename argument of execve() specifies an interpreter 174- script, then interpreter will be invoked with the following argu‐ 175- ments: 176- 177- interpreter [optional-arg] filename arg... 178- 179- where arg... is the series of words pointed to by the argv argu‐ 180- ment of execve(), starting at argv[1]. 181- 182- For portable use, optional-arg should either be absent, or be 183- specified as a single word (i.e., it should not contain white 184- space); see NOTES below. 185- 186- Since Linux 2.6.28, the kernel permits the interpreter of a script 187- to itself be a script. This permission is recursive, up to a 188- limit of four recursions, so that the interpreter may be a script 189- which is interpreted by a script, and so on. -- 343: Interpreter scripts 344- A maximum line length of 127 characters is allowed for the first 345- line in an interpreter scripts. 346- 347- The semantics of the optional-arg argument of an interpreter 348- script vary across implementations. On Linux, the entire string 349- following the interpreter name is passed as a single argument to 350- the interpreter, and this string can include white space. How‐ 351- ever, behavior differs on some other systems. Some systems use 352- the first white space to terminate optional-arg. On some systems, 353- an interpreter script can have multiple arguments, and white spa‐ 354- ces in optional-arg are used to delimit the arguments. 355- 356- Linux ignores the set-user-ID and set-group-ID bits on scripts.