在 Linux 和 BSD 中使用和不使用 shebang 执行 Bash 脚本
- 2024-11-11 08:27:00
- admin 原创
- 21
问题描述:
当类似 Bash 的脚本作为不带 shebang 的二进制文件执行时,如何以及由谁来决定执行什么?
我猜测使用shebang运行普通脚本是由binfmt_script Linux 模块处理的,该模块检查 shebang、解析命令行并运行指定的脚本解释器。
但是如果有人运行没有 shebang 的脚本会发生什么?我测试了直接execv
方法,发现其中没有内核魔法 - 即像这样的文件:
$ cat target-script
echo Hello
echo "bash: $BASH_VERSION"
echo "zsh: $ZSH_VERSION"
运行仅执行调用的已编译 C 程序execv
会产生以下结果:
$ cat 测试运行器.c
无效主(){
如果(execv(“。/target-script”,0)==-1)
错误();
}
$./测试运行器
./target-script:执行格式错误
但是,如果我从另一个 shell 脚本执行相同的操作,它将使用与原始脚本相同的 shell 解释器运行目标脚本:
$ cat 测试运行器.bash
/bin/bash #!/bin/bash
./目标脚本
$./test-runner.bash
你好
bash:4.1.0(1)-发布
zsh:
如果我对其他 shell (例如,Debian 的默认sh
- /bin/dash
) 执行同样的技巧,它也会起作用:
$ cat 测试运行器.dash
/bin/dash 的 #!/bin/dash
./目标脚本
$./test-runner.dash
你好
重击:
zsh:
奇怪的是,它与 zsh 的配合并不像预期的那样好,也不遵循一般的方案。看起来 zsh/bin/sh
毕竟是在这样的文件上执行的:
greycat@burrow-debian ~/z/test-runner $ cat test-runner.zsh
/bin/zsh #!/bin/zsh 复制代码
echo ZSH_VERSION=$ZSH_VERSION
./目标脚本
greycat@burrow-debian ~/z/test-runner $ ./test-runner.zsh
ZSH_版本=4.3.10
你好
重击:
zsh:
请注意,ZSH_VERSION
在父脚本中有效,但ZSH_VERSION
在子脚本中无效!
在没有 shebang 的情况下,shell(Bash、dash)如何确定要执行的内容?我曾尝试在 Bash/dash 源代码中挖掘该位置,但唉,看起来我有点迷失了方向。有人能解释一下在 Bash/dash 中确定没有 shebang 的目标文件应该作为脚本还是二进制文件执行的魔法吗?或者可能存在与内核/libc 的某种交互,然后我欢迎解释它在 Linux 和 FreeBSD 内核/libcs 中是如何工作的?
解决方案 1:
由于这发生在 dash 中,并且 dash 更简单,所以我首先在那里查看。
似乎 exec.c 是值得一看的地方,相关函数是tryexec
,每当 shell 需要执行命令时,都会调用shellexec
该函数。tryexec 函数(简化版本)如下:
STATIC void
tryexec(char *cmd, char **argv, char **envp)
{
char *const path_bshell = _PATH_BSHELL;
repeat:
execve(cmd, argv, envp);
if (cmd != path_bshell && errno == ENOEXEC) {
*argv-- = cmd;
*argv = cmd = path_bshell;
goto repeat;
}
}
_PATH_BSHELL
因此,如果出现,它总是用指向其自身的路径(默认为"/bin/sh"
)替换要执行的命令ENOEXEC
。这里真的没有什么魔法。
我发现 FreeBSD 在bash
和其自己的 中表现出相同的行为sh
。
处理这个问题的方法bash
类似,但要复杂得多。如果你想进一步了解它,我建议你阅读 bashexecute_command.c
并特别查看execute_shell_script
和 然后shell_execve
。注释非常具有描述性。
解决方案 2:
(看起来 Sorpigal 已经报道过了但是我已经把这个打出来了并且它可能会引起人们的兴趣。)
根据Unix FAQ 的第 3.16 节,shell 首先查看魔数(文件的前两个字节)。一些数字表示二进制可执行文件;#!
表示该行的其余部分应解释为 shebang。否则,shell 会尝试将其作为 shell 脚本运行。
此外,它似乎csh
查看第一个字节,如果是#
,它会尝试将其作为csh
脚本运行。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件