bash脚本执行有和没有在Linux和BSD家当 [英] Bash script execution with and without shebang in Linux and BSD

查看:129
本文介绍了bash脚本执行有和没有在Linux和BSD家当的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何,谁确定何时bash类似的脚本作为二进制没有家当执行什么执行?

How and who determines what executes when a Bash-like script is executed as a binary without a shebang?

我想这运行正常的脚本的的家当与处理<一个href=\"http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/fs/binfmt_script.c?id=HEAD\"相对=nofollow> binfmt_script Linux的模块,它检查一个家当,解析命令行并运行指定的脚本间preTER。

I guess that running a normal script with shebang is handled with binfmt_script Linux module, which checks a shebang, parses command line and runs designated script interpreter.

但是,当有人运行没有认领的脚本会发生什么?我测试过的直接 execv 办法并发现那里面有没有神奇的内核 - 即这样的文件:

But what happens when someone runs a script without a shebang? I've tested the direct execv approach and found out that there's no kernel magic in there - i.e. a file like that:

$ cat target-script
echo Hello
echo "bash: $BASH_VERSION"
echo "zsh: $ZSH_VERSION"

运行编译的C程序,它只是一个 execv 通话率:


$ cat test-runner.c
void main() {
        if (execv("./target-script", 0) == -1)
                perror();
}
$ ./test-runner
./target-script: Exec format error

但是,如果我这样做从另一个shell脚本同样的事情,它运行使用相同的外壳间preTER为原来的目标脚本:

However, if I do the same thing from another shell script, it runs the target script using the same shell interpreter as the original one:


$ cat test-runner.bash
#!/bin/bash
./target-script

$ ./test-runner.bash 
Hello
bash: 4.1.0(1)-release
zsh: 

如果我做其他炮弹同样的伎俩(例如,Debian的默认 SH - /斌/破折号 ),它也可以工作:

If I do the same trick with other shells (for example, Debian's default sh - /bin/dash), it also works:


$ cat test-runner.dash   
#!/bin/dash
./target-script

$ ./test-runner.dash 
Hello
bash: 
zsh: 

令人不解,但它确实如预期的zsh带和不遵循的总体方案不是那么回事。貌似毕竟执行 / bin / sh的对这些文件的zsh:


greycat@burrow-debian ~/z/test-runner $ cat test-runner.zsh 
#!/bin/zsh
echo ZSH_VERSION=$ZSH_VERSION
./target-script

greycat@burrow-debian ~/z/test-runner $ ./test-runner.zsh 
ZSH_VERSION=4.3.10
Hello
bash: 
zsh: 

注意 ZSH_VERSION 在父脚本的工作,而 ZSH_VERSION 在孩子没!

Note that ZSH_VERSION in parent script worked, while ZSH_VERSION in child didn't!

如何做一个外壳(猛砸,破折号)决定时,有没有什么家当被执行?我试图挖掘在猛砸/短跑源的地方,但是,唉,看来我在那里种丢失。任何人都可以提供一些线索上确定是否没有家当目标文件应该脚本或在猛砸/破折号的二进制执行的魔力?或者可能是有的某种内核/ libc的互动,然后我会欢迎它是如何在Linux和FreeBSD内核工作说明/ libcs​​?

How does a shell (Bash, dash) determines what gets executed when there's no shebang? I've tried to dig up that place in Bash/dash sources, but, alas, looks like I'm kind of lost in there. Can anyone shed some light on the magic that determines whether the target file without shebang should be executed as script or as a binary in Bash/dash? Or may be there is some sort of interaction with kernel / libc and then I'd welcome explanations on how does it work in Linux and FreeBSD kernels / libcs?

推荐答案

由于这发生在仪表板和仪表板更简单,我看着那里第一次。

Since this happens in dash and dash is simpler, I looked there first.

好像exec.c是看的地方,相关functionis是 tryexec ,这是从 shellexec 其中每当壳东西的命令需要执行被调用。及(简化版本)的tryexec功能如下:

Seems like exec.c is the place to look, and the relevant functionis are tryexec, which is called from shellexec which is called whenever the shell things a command needs to be executed. And (a simplified version of) the tryexec function is as follows:

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 出现。真的没有神奇的在这里。

So, it simply always replaces the command to execute with the path to itself (_PATH_BSHELL defaults to "/bin/sh") if ENOEXEC occurs. There's really no magic here.

我发现FreeBSD的表现相同的行为在庆典,并在其自己的 SH

I find that FreeBSD exhibits identical behavior in bash and in its own sh.

方式庆典处理这个问题是类似的,但要复杂得多。如果你想看看它进一步建议阅读的bash的 execute_command.c 并专门在 execute_shell_script ,然后寻找 shell_execve 。这些评论是相当的描述。

The way bash handles this is similar but much more complicated. If you want to look in to it further I recommend reading bash's execute_command.c and looking specifically at execute_shell_script and then shell_execve. The comments are quite descriptive.

这篇关于bash脚本执行有和没有在Linux和BSD家当的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆