Ang*_*rou 2 shell environment-variables shebang
我试图弄清楚 shebang 的语义到底是什么。
我可以写一个这样的脚本:
#!/usr/bin/env bash
if [ -z "$FOO" ]
then
echo "No FOO"
else
echo "$FOO"
fi
Run Code Online (Sandbox Code Playgroud)
在我的环境中没有$FOO
,并像 、 、 等一样运行它./foo.sh
,bash foo.sh
它将env bash foo.sh
按预期打印“No FOO”。
我当然可以像这样运行它FOO=bar ./foo.sh
并且它会打印bar
。
手册env
页给出的调用如下:
env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]
Run Code Online (Sandbox Code Playgroud)
我可以这样使用它:
$ env FOO=bar bash foo.sh
bar
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试在 shebang 中使用该语法:
env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]
Run Code Online (Sandbox Code Playgroud)
然后./foo.sh
无限期挂起并且不执行。
谁可以给我解释一下这个?我假设当遇到 shebang 时,它只是复制命令,将脚本的路径附加到参数列表的末尾,然后执行它,但这种行为表明情况并非如此。
大多数系统在 shebang 行中解释器路径之后最多只接受一个参数。如果您提供多个,则行为取决于系统。
\n在 Linux 上,解释器后面的所有内容(没有前导和尾随空格或制表符)都作为单个参数传递。所以,伴随着一声:
\n#! /usr/bin/env FOO=bar bash\n
Run Code Online (Sandbox Code Playgroud)\n系统将/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
解决该限制。
在
\n#! /usr/bin/env -S FOO=bar bash\n
Run Code Online (Sandbox Code Playgroud)\n单个"-S FOO=bar bash"
参数仍将传递给env
,但env
会拆分"\xc2\xa0FOO=bar bash"
该选项的参数-S
,并且其行为就像使用FOO=bar
和 作为bash
单独的参数调用一样。
有关如何完成拆分的详细信息,请参阅GNUenv
手册或FreeBSDenv
手册。