为什么 FOO=bar; 将变量导出到我的环境中

Jus*_*son 4 shell bash environment-variables

如果我跑

FOO=bar docker run -it -e FOO=$FOO debian env
Run Code Online (Sandbox Code Playgroud)

该环境变量未在命令的命令输出中设置env

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=03f3b59c0aab
TERM=xterm
FOO=
HOME=/root
Run Code Online (Sandbox Code Playgroud)

但如果我跑

FOO=bar; docker run -i -t --rm -e FOO=$FOO debian:stable-slim env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=672bfdcde93c
TERM=xterm
FOO=bar
HOME=/root
Run Code Online (Sandbox Code Playgroud)

然后该变量可以从容器中获得,也可以导出到我当前的 shell 环境中。

echo $FOO
bar
Run Code Online (Sandbox Code Playgroud)

我期待这种行为,export FOO=bar但为什么;也会发生这种情况?

ImH*_*ere 20

不,FOO=bar;不会将变量导出到我的环境中

仅当先前导出时,才会在(当前)环境中设置 var:

$ export foo
$ foo=bar
$ env | grep foo
foo=bar
Run Code Online (Sandbox Code Playgroud)

当一个变量被放置在命令之前时,它会在命令的环境中设置。喜欢foo=bar command。它只在命令运行时存在。

$ foo=bar bash -c 'echo "foo is = $foo"'
foo is = bar
Run Code Online (Sandbox Code Playgroud)

没有为命令行设置 var(在当前 shell 中):

$ foo=bar bash -c echo\ $foo
Run Code Online (Sandbox Code Playgroud)

上面,当前运行的 shell$foo没有替换的值,因此:没有输出。

你的命令:

$ FOO=bar docker run -it -e FOO=$FOO debian env
Run Code Online (Sandbox Code Playgroud)

转换为实际字符串:

$ FOO=bar docker run -it -e FOO= debian env
Run Code Online (Sandbox Code Playgroud)

通过当前运行的 shell

相反,如果您foo=bar在运行命令之前设置变量(在当前运行的 shell 中),则该行将转换为:

$ FOO=bar; docker run -it -e FOO=bar debian env
Run Code Online (Sandbox Code Playgroud)

当命令返回时,设置为命令环境的变量将被删除:

$ foo=bar bash -c 'echo'; echo "foo was erased: \"$foo\""
Run Code Online (Sandbox Code Playgroud)

除非命令在某些条件/shell 中是内置命令:

$ ksh -c 'foo=bar typeset baz=quuz; echo $foo'
bar
Run Code Online (Sandbox Code Playgroud)

  • 变量 `FOO` 也不会导出到当前的 shell 环境,而是设置为 shell 变量,除非它之前已经导出。 (2认同)

And*_*ton 12

有许多变化需要考虑:

  1. 只是FOO=bar创建一个名为FOOvalue的变量bar,但该变量不会传递给新进程:

    $ echo $FOO
    $ FOO=bar
    $ echo $FOO
    bar
    $ bash        # Start a new bash process
    $ echo $FOO
                  # Variable is not set in the new process
    $ exit        # Exit new bash process
    
    Run Code Online (Sandbox Code Playgroud)
  2. 运行FOO=bar <command>将使用变量集运行给定的命令(但不影响原始 shell 的环境):

    $ echo $foo
    $ FOO=baz bash   # start a new bash process
    $ echo $FOO
    baz
    $ exit           # exit the new bash process
    exit
    $ echo $FOO      
                     # No FOO in the original bash process
    $
    
    Run Code Online (Sandbox Code Playgroud)
  3. FOO=foo; <command>等价于(1);在两个命令之间放置分号相当于在两个单独的行上运行这两个命令:

    $ FOO=foo; echo $FOO
    foo
    $ bash
    $ echo $FOO
    
    $ exit
    exit
    $ echo $FOO
    foo
    $
    
    Run Code Online (Sandbox Code Playgroud)
  4. Usingexport会将 shell 环境中的变量传递给新创建的进程:

    $ export FOO=bar
    $ echo $FOO    # Value set in original shell
    bar
    $ bash         # Start another shell
    $ echo $FOO
    bar            # Value was passed along to new process
    $ exit
    exit
    
    Run Code Online (Sandbox Code Playgroud)


piz*_*ect 8

FOO=bar docker run -it -e FOO=$FOO debian env

这里$FOOfromFOO=$FOO将在分配发生之前扩展FOO=bar

您可以使用更直接的示例进行检查:

FOO=first
FOO=second echo FOO=$FOO
=> FOO=first

FOO=third; echo FOO=$FOO
=> FOO=third
Run Code Online (Sandbox Code Playgroud)

FOO=bar cmd形式将真正建立FOO=bar在环境cmd,但像这样的命令docker不其自动导出自己的环境,放入容器内,但环境瓦尔必须与明确的添加-e开关。

同样,一个更直接的演示是:

FOO=before
FOO=after env - FOO=$FOO printenv FOO
=> before
Run Code Online (Sandbox Code Playgroud)