私はshebangの意味が何であるかを理解しようとしています。
次のスクリプトを作成できます。
#!/usr/bin/env bash
if [ -z "$FOO" ]
then
echo "No FOO"
else
echo "$FOO"
fi
私の環境ではなく$FOO
、などのように実行すると予想通り「No FOO」が印刷されます。./foo.sh
bash foo.sh
env bash foo.sh
もちろん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が発生した場合は、コマンドをコピーし、引数リストの末尾にスクリプトパスを追加して実行すると仮定しましたが、この動作はそうではないことを意味します。
答え1
ほとんどのシステムは最大一つshebang 行のインタプリタパスの後の引数です。 1 つ以上のアイテムを提供する場合、動作はシステムによって異なります。。
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
よりGNUenv
マニュアルまたはFreeBSDenv
マニュアル分割の実行方法の詳細。