命令有什么区别
$ env FOO=bar baz
和
$ FOO=bar baz
有什么作用呢env
?
答案1
它们在功能上是等效的。
主要区别在于env FOO=bar baz
涉及调用 shell 和 之间的中间进程baz
,而FOO=bar baz
shell 直接调用baz
.
所以从这方面来说,FOO=bar baz
是首选。
我发现自己使用的唯一情况env FOO=bar
是我必须将一个命令传递给另一个命令。
作为一个具体的示例,假设我有一个包装器脚本,它对环境执行一些修改,然后调用传递exec
给它的命令,例如:
#!/bin/bash
FOO=bob
some stuff
exec "$@"
如果你执行它myscript FOO=bar baz
,exec
将会抛出一个错误,因为它exec FOO=bar baz
是无效的。
相反,您将其称为 as ,myscript env FOO=bar baz
其执行为exec env FOO=bar baz
,并且是完全有效的。
答案2
baz
在此特定示例中,假设您的 shell 是 POSIX 兼容 shell,并且假设是可执行文件而不是内置 shell,则没有任何有效区别。
如果你的外壳是不是POSIX 兼容的 shell,例如csh
或tcsh
,语法
FOO=bar baz
不起作用,并且没有等效的 shell 语法。对于这些 shell,该env
命令是覆盖或注入单个命令的环境变量的唯一方法。
例如,如果baz
是 shell 内置命令,fc
则env
不会给出相同的结果,因为env
正在执行新进程而不是由命令 shell 直接运行。此外,没有fc
可执行文件,由于它与 shell 环境交互的方式,它只能作为 shell 内置命令运行,env
因此绝不使用像fc
.
此外,还env
提供了一个-i
选项,允许您在仅具有指定环境变量集的空环境中启动命令。例如,这env
对于在净化环境中启动进程非常有用
env -i HOME=/tmp/homedir "PATH=`getconf PATH`" "TERM=$TERM" FOO=bar baz
答案3
除了已经说过的
VAR=value cmd args > redirs
作为 shell (Bourne/POSIX) 功能,您传递给的环境变量的名称受到限制cmd
。它们必须是有效的 shell 变量名称,并且不能是 shell 的只读变量或特殊变量。
例如,你不能这样做:
1=foo cmd
或者
+++=bar cmd
bash
不允许你做:
SHELLOPTS=xtrace cmd
虽然你可以这样做:
env 1=foo cmd
env +++=bar cmd
env '=baz' cmd
(不是说你想要或应该想要这样做)。或者:
env SHELLOPTS=xtrace cmd
(我有时需要这样做)。
请注意,env
您仍然无法传递不包含 a 的环境变量字符串=
(您也不想这样做)。
答案4
另一种真正有用的情况env
是,如果您想完全控制环境。我运行一个服务器程序(Informix,以防你猜不到),我想完全控制其环境。我在脚本末尾使用它来运行它env
,该脚本将一堆变量设置为正确的值:
env -i HOME="$IXD" \
INFORMIXDIR="$IXD" \
INFORMIXSERVER="$IXS" \
${IXC:+INFORMIXCONCSMCFG="$IXC"} \
${IXH:+INFORMIXSQLHOSTS="$IXH"} \
IFX_LISTEN_TIMEOUT=3 \
ONCONFIG="onconfig.$IXS" \
PATH="/bin:/usr/bin:$IXD/bin" \
SHELL=/bin/ksh \
TZ=UTC0 \
$ONINIT "$@"
该-i
选项会破坏现有环境。后续VAR=value
选项设置我想要设置的环境变量;程序的名称在 中$ONINIT
,所有命令行参数都通过 逐字传递"$@"
。
该${IXH:+INFORMIXSQLHOSTS="$IXH"}
构造仅传递INFORMIXSQLHOSTS="$IXH"
给env
if$IXH
设置为非空值。