为什么您可以在bash,zsh或sh中执行一个空文件,而当带有空文件的execve syscall退出ENOEXEC时,它将退出代码0?
touch zero
chmod +x zero
./zero
echo $?
0
execve
以ENOEXEC Exec format error
退出-1,因此这不是操作系统行为。
strace -f ./zero
execve("./zero", ["./zero"], [/* 53 vars */]) = -1 ENOEXEC (Exec format error)
write(2, "strace: exec: Exec format error\n", 32strace: exec: Exec format error
) = 32
exit_group(1) = ?
+++ exited with 1 +++
sh还调用execve并获取-ENOEXEC,但它继续读取文件的80个字节并退出零。
strace -f sh -c "./zero"
...
execve("./zero", ["./zero"], [/* 52 vars */]) = -1 ENOEXEC (Exec format error)
open("./zero", O_RDONLY) = 3
read(3, "", 80) = 0
close(3) = 0
exit_group(0)
答案 0 :(得分:2)
如果execve(2)
返回错误并将errno
设置为ENOEXEC
,则所有shell将尝试将可执行文件作为shell脚本运行,即。他们将使用给出的文件作为参数执行shell。空脚本的退出状态为零(=成功)[1]。
它们将确切运行什么shell取决于:bash
,ksh93
和yash
将自己运行脚本; csh
,dash
,zsh
或mksh
将始终使用/bin/sh
运行它。
此行为非常古老,并且早于she-bang功能和标准化的可执行文件格式,而且该也是标准要求的-请阅读该标准Command Search and Execution的第2节。
execve
以-1
ENOEXEC
退出Exec format error
,因此这不是操作系统行为。
然而,execvp()
和execlp()
库包装程序是standard必需的行为:
如果exec系列的其他成员 函数将失败,并将
errno
设置为ENOEXEC
,execlp()
和execvp()
函数应执行命令解释器,并且 执行的命令的环境应类似于进程使用sh
调用execl()
实用程序,如下所示:execl(<shell path>, arg0, file, arg1, ..., (char *)0);`
[1]在较旧的系统/bin/true
上是一个仅包含版权声明的文件,该文件声明其为“ AT&T的未发布专有源代码”。