我了解到,在脚本语言中,您可以在文件中使用shebang来指示您打算使用的语言和版本。否则,命令./script_name
将默认使用bash作为解释器。
为什么bash不尝试使用相同的命令样式./executable
来解释编译的程序?换句话说,bash特别指出了什么来区分脚本和可执行文件?
答案 0 :(得分:1)
答案很复杂。
exec
系统调用来执行程序。唯一的例外是当exec
调用返回errno
-ENOEXEC
时,它会尝试使自己成为解释器。
在这种情况下,shebang由内核处理。所有shell(例如bash)都会在exec(2)
系列调用中执行系统调用,以请求运行程序。
内核本身负责弄清楚如何处理它。它了解一大堆可执行格式,如AOUT,ELF,COFF和是SHEBANG。
相关代码可在fs/binfmt_script.c
的Linux内核树中找到,当然也可以在fs/exec.c
中找到
static int load_script(struct linux_binprm *bprm)
实际执行脚本加载并执行适当的二进制文件。
现在,如果您查看该代码,您会注意到around line 58如果找不到解释器条目,它将返回-ENOEXEC
。
但是,如果找到解释器条目(并且所有其他条件都可以),则按预期继续执行
那么当没有找到解释器条目时会发生什么?
这意味着脚本在第一行中没有#!
,正如内核所期望的那样。
在这种情况下,bash(以及其他交互式shell)继续尝试将自己注入解释器或系统默认shell(例如/ bin / sh)作为解释器。
现在更多bash is doing
我建议您使用以下内容创建一个简单的shell脚本 foo :
# Shebang would go here
# This is foo
echo "Hello World"
chmod a+x foo
然后用strace运行foo:
strace ./foo
然后用strace运行它,但是调用bash并让它运行foo:
strace /bin/bash -c ./foo
现在注入#!/bin/sh
并再次重复这两个步骤。
答案 1 :(得分:1)
可执行文件以magic number开头 - 一个短字节序列,用于标识文件的格式。例如,ELF格式的可执行文件以\x7FELF
(十六进制:7f 45 4c 46)等开头.shebang,#!
(十六进制:23 21)实际上是一个幻数本身,它将文件标识为一个脚本。这就是为什么shebang 必须正好在文件的开头,而不是(例如)用空格缩进。
当要求系统执行"执行"一个文件,它读取前几个字节并根据它确定要做什么。 bash运行未识别(没有已知的幻数)文件作为bash scrips是一种特殊情况 - 如果系统无法弄清楚如何执行该文件,bash会尝试这样做。