由于文件不是系统识别的任何可执行文件类型,并且假设您具有执行该文件的权限,因此execve()系统调用通常会失败,并显示ENOEXEC(不是可执行文件)错误。
然后发生什么取决于用于执行命令的应用程序和/或库函数。
例如,可以是一个外壳,即execlp()/ execvp()libc函数。
大多数其他应用程序在运行命令时将使用其中任何一个。他们将通过system("command line")libc函数调用外壳程序,该函数通常将调用sh该命令行以解析该命令行(可以在编译时确定其路径(例如/bin/shvs /usr/xpg4/bin/sh在Solaris上)),或者$SHELL像它们自己那样调用存储在其中的shell vi使用其 !命令或xterm -e 'command line'其他命令(su user -c将调用用户的登录shell而不是$SHELL)。
通常,不以shebang开头的无Shebang文本文件#被视为sh脚本。这sh是会有所不同,虽然。
execlp()/ execvp(),在execve()返回ENOEXEC通常会调用sh就可以了。对于具有多个sh标准的系统(因为它们可以符合多个标准),sh通常将在编译时(通过使用execvp()/ execlp()通过链接指向的不同路径的不同代码块sh)确定该标准。例如,在Solaris上,它可以是/usr/xpg4/bin/sh(标准POSIX sh),也可以是(/bin/sh在Solaris 10及更高版本上的Bourne shell(过时的shell),在Solaris 11中是ksh93)。
关于外壳,有很多变化。bash,AT&T ksh,Bourne Shell通常会exec在模拟a之后,自己解释脚本本身(除非使用子进程,否则将在子进程中)execve(),即未设置所有未导出的变量,关闭所有close-on-exec fds,删除所有自定义陷阱,别名,函数...(bash将以sh模式解释脚本)。yash将执行自身(在模式下sh也是argv[0]这样sh)以对其进行解释。
zsh,pdksh,ash基壳通常将调用sh(在编译时间,其中所确定的路径)。
对于csh和tcsh(以及sh某些早期BSD的),如果文件的第一个字符是#,则它们将执行自身以对其进行解释,sh否则。那可以追溯到shebang之前的一段时间,在那个csh时候确实可以识别#为注释,但不能识别为Bourne shell,因此这#暗示它是一个csh脚本。
fish(至少是2.4.0版),如果execve()失败则仅返回错误(它不会尝试将其视为脚本)。
某些shell(例如bash或AT&T ksh)将首先尝试试探性地确定文件是否可能是脚本。因此,您可能会发现,如果前几个字节中包含NUL字符,则某些外壳程序将拒绝执行脚本。
另请注意,如果execve()ENOEXEC失败,但文件确实包含shebang行,则某些shell会尝试自行解释shebang行。
举几个例子:
- 如果
$SHELL是/bin/bash,xterm -e 'myscript with args'将已myscript被解释bash的sh方式。与一起使用时xterm -e myscript with args,xterm将使用execvp()来解释脚本sh。
su -c myscript在Solaris 10中,root登录外壳是Bourne外壳/bin/sh,/bin/sh现在是Bourne外壳将由Bourne外壳myscript解释。
/usr/xpg4/bin/awk 'BEGIN{system("myscript")'在Solaris 10上,它将由解释/usr/xpg4/bin/sh(与相同/usr/xpg4/bin/env myscript)。
find . -prune -exec myscript {} \;在Solaris 10上(使用execvp()),即使在POSIX环境中(一致性错误),也将使用/bin/sh即使使用来解释它/usr/xpg4/bin/find。
csh -c myscriptcsh如果以开头#,则以解释,sh否则为。
总而言之,如果您不知道该脚本的调用方式和调用方式,则无法确定将使用哪个shell来解释该脚本。
在任何情况下,read -p都是bash-only语法,因此您需要确保脚本由解释bash(并避免使用误导性的.sh扩展名)。您要么知道bash可执行文件的路径,然后使用:
#! /path/to/bash -
read -p ...
或者您可以尝试通过以下方式依赖于可执行文件的$PATH查找bash(假设bash已安装):
#! /usr/bin/env bash
read -p ...
(env几乎在中普遍存在/usr/bin)。或者,可以使它与POSIX + Bourne兼容/bin/sh。所有系统都有一个/bin/sh。在大多数情况下,它将(大多数情况下)与POSIX兼容,但是您可能仍然会发现Bourne shell时不时出现。
#! /bin/sh -
printf >&2 'Enter a user name: '
read user
printf '%s\n' "$user"