簡體   English   中英

在Linux和BSD中使用和不使用shebang執行Bash腳本執行

[英]Bash script execution with and without shebang in Linux and BSD

當一個類似Bash的腳本作為沒有shebang的二進制文件執行時,如何以及由誰決定執行什么?

我想 shebang運行一個普通的腳本是用binfmt_script Linux模塊處理的,它檢查一個shebang, parses命令行並運行指定的腳本解釋器。

但是當有人在沒有shebang的情況下運行腳本時會發生什么? 我已經測試了直接execv方法,發現那里沒有內核魔法 - 即一個像這樣的文件:

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

運行只執行execv調用的已編譯C程序會產生:

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

但是,如果我從另一個shell腳本執行相同的操作,它將使用與原始shell腳本相同的shell解釋器運行目標腳本:

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

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

如果我對其他shell執行相同的技巧(例如,Debian的默認sh - /bin/dash ),它也可以:

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

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

神秘的是,它與zsh沒有達到預期的效果,並且不遵循一般方案。 畢竟看起來像zsh執行/bin/sh這樣的文件:

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中的ZSH_VERSION沒有!

如果沒有shebang,shell(Bash,破折號)如何確定執行的內容? 我試圖在Bash / dash來源中挖掘那個地方,但是,唉,看起來我有點迷失在那里。 任何人都可以了解決定在沒有shebang的目標文件是作為腳本執行還是作為Bash / dash中的二進制執行的魔法? 或者可能是某種內核/ libc的互動,然后我會歡迎它是如何在Linux和FreeBSD內核/ libcs工作的解釋?

由於這種情況發生在破折號和破折號更簡單,我先看了一下。

看起來像exec.c是看的地方,相關的函數是tryexec ,它是從shellexec調用的,只要shell需要執行命令就會調用它。 而且(簡化版)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;
        }
}

因此,如果發生ENOEXEC ,它只是總是將命令替換為自身路徑( _PATH_BSHELL默認為"/bin/sh" )。 這里真的沒有魔力。

我發現FreeBSD在bash和它自己的sh表現出相同的行為。

bash處理它的方式類似但更復雜。 如果你想進一步研究它,我建議你閱讀bash的execute_command.c並專門查看execute_shell_script然后再查看shell_execve 評論非常具有描述性。

(看起來Sorpigal已經覆蓋了它,但我已經輸入了它,它可能是有意義的。)

根據Unix FAQ的3.16節 ,shell首先查看幻數(文件的前兩個字節)。 一些數字表示二進制可執行文件 #! 表示該行的其余部分應解釋為shebang。 否則,shell會嘗試將其作為shell腳本運行。

另外,似乎csh查看了第一個字節,如果它是# ,它將嘗試將其作為csh腳本運行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM