![](/img/trans.png)
[英]what function in Linux API implements execution of a script file with a shebang?
[英]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.