Shell
#!/usr/bin/env 因 NAME=VALUE 而掛起
我試圖弄清楚shebang的語義到底是什麼。
我可以寫一個這樣的腳本:
#!/usr/bin/env bash if [ -z "$FOO" ] then echo "No FOO" else echo "$FOO" fi
沒有
$FOO
在我的環境中,並像./foo.sh
,bash foo.sh
,env bash foo.sh
等一樣執行它,它將按預期列印“No FOO”。我當然可以執行它
FOO=bar ./foo.sh
,它會列印bar
。手冊頁給出的
env
呼叫如下:env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]
我可以這樣使用它:
$ env FOO=bar bash foo.sh bar
但是,如果我嘗試在 shebang 中使用該語法:
#!/usr/bin/env FOO=bar bash if [ -z "$FOO" ] then echo "No FOO" else echo "$FOO" fi
然後
./foo.sh
無限期掛起並且不執行。誰可以給我解釋一下這個?我假設當遇到 shebang 時,它只是複制命令,將腳本的路徑附加到參數列表的末尾,然後執行它,但這種行為表明並非如此。
大多數係統在 shebang 行中的解釋器路徑之後最多只接受**一個參數。**如果您提供多個,則行為取決於系統。
在 Linux 上,解釋器之後的所有內容(沒有前導和尾隨空格或製表符)作為單個參數傳遞。因此,隨著她的一聲巨響:
#! /usr/bin/env FOO=bar bash
系統將
/usr/bin/env
使用FOO=bar bash
和/path/to/the/script
作為參數呼叫。然後env
將在其環境中再次執行腳本,而FOO=bar bash
不是作為參數(和環境中),從而導致無限循環。bash``/path/to/the/script``FOO=bar
一些實現
env
,包括 FreeBSD 和 GNU 的最新版本env
,可以被告知自己進行拆分-S
以解決該限制。在
#! /usr/bin/env -S FOO=bar bash
"-S FOO=bar bash"
單個參數仍將被傳遞給,env
但env
會拆分該選項的" FOO=bar bash"
參數,-S
並表現得就像使用FOO=bar
和bash
作為單獨的參數呼叫一樣。有關如何進行拆分的詳細資訊,請參閱GNU
env
手冊或FreeBSDenv
手冊。