Shell

#!/usr/bin/env 因 NAME=VALUE 而掛起

  • September 23, 2021

我試圖弄清楚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"單個參數仍將被傳遞給,envenv會拆分該選項的" FOO=bar bash"參數,-S並表現得就像使用FOO=barbash作為單獨的參數呼叫一樣。

有關如何進行拆分的詳細資訊,請參閱GNUenv手冊FreeBSDenv手冊。

引用自:https://unix.stackexchange.com/questions/670334