web-dev-qa-db-ja.com

プロセスが親の環境を継承する場合、なぜエクスポートが必要なのですか?

私は here を読みました。シェルでのexportの目的は、シェルから開始されたサブプロセスで変数を使用できるようにすることです。

しかし、私は here および here that「プロセスは親(プロセスを開始したプロセス)から環境を継承します」も読んだ。

この場合、exportが必要なのはなぜですか?何が欠けていますか?

シェル変数はデフォルトで環境の一部ではありませんか?違いはなんですか?

75

シェル変数は環境内であると想定しています。これは誤りです。 exportコマンドは、環境に存在する名前を定義するものです。したがって:

_a=1 b=2
export b
_

結果は現在のShellであり、_$a_は1に、_$b_は2に展開されますが、サブプロセスはaの一部ではないため、環境(現在のシェルでも)。

いくつかの便利なツール:

  • set:現在のシェルのパラメーターを表示するのに便利です。
  • _set -k_:環境に割り当てられた引数を設定します。検討するf() { set -k; env; }; f a=1
  • _set -a_:設定された名前を環境に設定するようにシェルに指示します。すべての割り当ての前にexportを置くのと同じです。 _.env_のように、_set -a; . .env; set +a_ファイルに役立ちます。
  • export:環境に名前を付けるようシェルに指示します。エクスポートと割り当ては2つのまったく異なる操作です。
  • env:外部コマンドとして、envinherited環境についてのみ通知できるため、健全性チェックに役立ちます。
  • _env -i_:サブプロセスを開始する前に環境をクリアするのに役立ちます。

exportの代替:

  1. _name=val command_#コマンドの前の割り当ては、その名前をコマンドにエクスポートします。
  2. _declare/local -x name_#名前をエクスポートします。特に、名前をスコープ外に公開したくない場合にシェル関数で役立ちます。
  3. _set -a_#次のすべての割り当てをエクスポートします。
79
kojiro

シェル変数と環境変数には違いがあります。 exportingなしでシェル変数を定義すると、その変数はプロセス環境に追加されないため、その子には継承されません。

exportを使用して、シェルにShell変数を環境に追加するように指示します。これは、printenvを使用してテストできます(これは、環境をstdoutに出力します。これは、exporting変数の影響を見る子プロセスであるためです)。

#!/bin/sh

MYVAR="my cool variable"

echo "Without export:"
printenv | grep MYVAR

echo "With export:"
export MYVAR
printenv | grep MYVAR
24
Andreas Wiese

変数は、エクスポートされると環境の一部になります。 PATHはシェル自体にエクスポートされますが、カスタム変数は必要に応じてエクスポートできます。いくつかのセットアップコードを使用:

$ cat subshell.sh 
#!/usr/bin/env bash
declare | grep -e '^PATH=' -e '^foo='

比較する

$ cat test.sh 
#!/usr/bin/env bash
export PATH=/bin
export foo=bar
declare | grep -e '^PATH=' -e '^foo='
./subshell.sh
$ ./test.sh 
PATH=/bin
foo=bar
PATH=/bin
foo=bar

$ cat test2.sh 
#!/usr/bin/env bash
PATH=/bin
foo=bar
declare | grep -e '^PATH=' -e '^foo='
./subshell.sh
$ ./test2.sh 
PATH=/bin
foo=bar
PATH=/bin

fooはシェルによってエクスポートされず、test2.shはエクスポートされなかったため、前回の実行ではsubshell.shの環境の一部ではありませんでした。

6
l0b0