当类似 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 test-runner.c 无效的主要(){ if (execv("./target-script", 0) == -1) 错误(); } $ ./test-runner ./target-script: 执行格式错误
但是,如果我从另一个 shell 脚本执行相同的操作,它会使用与原始脚本相同的 shell 解释器运行目标脚本:
$ cat test-runner.bash #!/bin/bash ./目标脚本 $ ./test-runner.bash 你好 bash:4.1.0(1)-发布 zsh:
如果我对其他 shell 执行相同的技巧(例如,Debian 的默认sh
- /bin/dash
),它也可以:
$ cat test-runner.dash #!/bin/破折号 ./目标脚本 $ ./test-runner.dash 你好 重击: zsh:
奇怪的是,它与 zsh 并没有像预期的那样工作,并且不遵循一般方案。看起来 zsh/bin/sh
毕竟是在这些文件上执行的:
graycat@burrow-debian ~/z/test-runner $ cat test-runner.zsh #!/bin/zsh 回声 ZSH_VERSION=$ZSH_VERSION ./目标脚本 graycat@burrow-debian ~/z/test-runner $ ./test-runner.zsh ZSH_VERSION=4.3.10 你好 重击: zsh:
请注意,ZSH_VERSION
在父脚本中有效,而ZSH_VERSION
在子脚本中没有!
shell(Bash,dash)如何确定没有shebang时执行的内容?我试图在 Bash/dash 源中挖掘那个地方,但是,唉,看起来我有点迷失在那里。任何人都可以阐明确定没有shebang的目标文件应该作为脚本还是作为Bash / dash中的二进制文件执行的魔法?或者可能与内核/ libc有某种交互,然后我欢迎解释它如何在 Linux 和 FreeBSD 内核/ libcs 中工作?