web-dev-qa-db-ja.com

なぜFOO = barなのですか?変数を環境にエクスポートする

走れば

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

その環境変数は、envコマンドのコマンド出力に設定されていません。

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=03f3b59c0aab
TERM=xterm
FOO=
HOME=/root

でも走ったら

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

その後、変数はコンテナーから利用可能になり、現在のシェル環境にもエクスポートされます。

echo $FOO
bar

export FOO=barしかし、なぜ;も?

4
Rothgar

いいえ、FOO = bar;は変数を環境にエクスポートしません

Varは、以前にエクスポートされた場合にのみ(現在の)環境で設定されます。

$ export foo
$ foo=bar
$ env | grep foo
foo=bar

変数は、コマンドの前に置かれると、コマンドの環境で設定されます。 foo=bar commandのように。また、コマンドの実行中にのみ存在します。

$ foo=bar bash -c 'echo "foo is = $foo"'
foo is = bar

Varは(現在のシェルでは)コマンドラインに設定されていません。

$ foo=bar bash -c echo\ $foo

上記では、$fooの値は何も現在実行中のシェルに置き換えられていないため、出力はありません。

あなたのコマンド:

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

実際の文字列に変換されます:

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

現在実行中のシェルによる

代わりに、コマンドを実行する前にfoo=barを使用して(現在実行中のシェルで)変数を設定すると、行は次のように変換されます。

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

コマンドの環境に設定された変数は、コマンドが戻ると消去されます。

$ foo=bar bash -c 'echo'; echo "foo was erased: \"$foo\""

例外コマンドが一部の条件/シェルで組み込みの場合:

$ ksh -c 'foo=bar typeset baz=quuz; echo $foo'
bar
20
Isaac

考慮すべきバリエーションがいくつかあります。

  1. ただやっているFOO=barは、FOOという名前の変数を作成し、値は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
    
  2. ランニング FOO=bar <command>は、指定されたコマンドを変数セットで実行します(ただし、元のシェルの環境には影響しません)。

    $ 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
    $
    
  3. やっているFOO=foo; <command>は(1)と同等です。 2つのコマンドの間にセミコロンを置くことは、2つのコマンドを2つの別々の行で実行することと同じです。

    $ FOO=foo; echo $FOO
    foo
    $ bash
    $ echo $FOO
    
    $ exit
    exit
    $ echo $FOO
    foo
    $
    
  4. exportを使用すると、シェルの環境の変数が新しく作成されたプロセスに渡されます。

    $ 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
    
12
Andy Dalton

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

ここで、$FOOFOO=$FOOが展開されますbeforeFOO=bar割り当てが発生します。

より簡単な例でそれを確認できます:

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

FOO=third; echo FOO=$FOO
=> FOO=third

FOO=bar cmdフォームは実際にcmdの環境でFOO=barを設定しますが、dockerのようなコマンドは自動的にをエクスポートしませんown環境をコンテナに追加しますが、-eスイッチを使用して環境変数を明示的に追加する必要があります。

繰り返しますが、より簡単なデモは次のとおりです。

FOO=before
FOO=after env - FOO=$FOO printenv FOO
=> before
8
pizdelect