export
とは何ですか?
違いは何ですか:
export name=value
そして
name=value
export
は、変数をサブプロセスで利用できるようにします。
あれは、
export name=value
その変数名は 任意のプロセスで利用可能であることを意味します あなたはそのシェルプロセスから実行します。プロセスにこの変数を利用させたい場合は、export
を使用し、そのシェルからプロセスを実行します。
name=value
変数の有効範囲はシェルに限定され、他のプロセスでは使用できないことを意味します。これはループ変数、一時変数などに使用します。
変数をエクスポートしても、それが親プロセスで使用可能にならないことに注意することが重要です。つまり、生成されたプロセスで変数を指定してエクスポートしても、それを起動したプロセスで使用できるようにはなりません。
他の答えが言っていることを説明するために:
$ foo="Hello, World"
$ echo $foo
Hello, World
$ bar="Goodbye"
$ export foo
$ bash
bash-3.2$ echo $foo
Hello, World
bash-3.2$ echo $bar
bash-3.2$
他の人は、輸出は変数をサブシェルに利用可能にし、それは正しいが単なる副作用であると答えた。変数をエクスポートすると、その変数は現在のシェルの環境に置かれます(すなわち、シェルはputenv(3)またはsetenv(3)を呼び出します)。プロセスの環境はexec全体に継承され、変数はサブシェル内に表示されます。
編集(5年間の観点から):これはばかげた答えです。 'export'の目的は、それらのコマンドがサブシェルであろうとサブプロセスであろうと、変数を「その後に実行されるコマンドの環境内に置く」ことです。単純な実装は単に変数をシェルの環境に置くことですが、これはexport -p
を実装することを不可能にします。
サブシェルを生成するときにbashでエクスポートする必要はないと言われていますが、他の人は正反対のことを言いました。サブシェル(()
、``
、$()
、またはloopsによって作成されるもの)とサブプロセス(名前によって呼び出されるプロセス、たとえばスクリプトに現れるリテラルbash
)との違いに注意することが重要です。
これら2つの構成要素に共通するのは、どちらも親シェルに変数を渡すことができないということです。
$ noexport=noexport; export export=export; (echo subshell: $noexport $export; subshell=subshell); bash -c 'echo subprocess: $noexport $export; subprocess=subprocess'; echo parent: $subshell $subprocess
subshell: noexport export
subprocess: export
parent:
混乱の原因がもう1つあります。「フォークされた」サブプロセスは、エクスポートされていない変数を見ないものだと考える人もいます。通常、fork()の直後にexec()が続きます。そのため、fork()が実際にはexec()であると見なすことになります。 exec
コマンドを使用すると、最初にfork()を実行せずにコマンドを実行できます。このメソッドによって開始されたプロセスも、エクスポートされていない変数にアクセスすることはできません。
$ noexport=noexport; export export=export; exec bash -c 'echo execd process: $noexport $export; execd=execd'; echo parent: $execd
execd process: export
今回はparent:
行が表示されないことに注意してください。これは、親シェルをexec
コマンドに置き換えたためです。そのため、そのコマンドを実行するためのものは残っていません。
サブプロセスにとって意味のある設定と変数についてはexport NAME=value
。
現在のシェルプロセス専用の一時変数またはループ変数の場合はNAME=value
。
より詳細には、export
は、作成時にサブプロセスとそのサブプロセスにコピーする環境内の変数名を示します。サブプロセスからコピーされた名前や値はありません。
よくあるエラーは等号の周りにスペースを入れることです。
$ export FOO = "bar"
bash: export: `=': not a valid identifier
エクスポートされた変数(B
)のみがサブプロセスに表示されます。
$ A="Alice"; export B="Bob"; echo "echo A is \$A. B is \$B" | bash
A is . B is Bob
サブプロセスを変更してもメインシェルは変わりません。
$ export B="Bob"; echo 'B="Banana"' | bash; echo $B
Bob
エクスポート用にマークされた変数は、サブプロセスの作成時に値がコピーされます。
$ export B="Bob"; echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash &
[1] 3306
$ B="Banana"; echo '(sleep 30; echo "Subprocess 2 has B=$B")' | bash
Subprocess 1 has B=Bob
Subprocess 2 has B=Banana
[1]+ Done echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash
エクスポートされた変数のみが環境の一部になります(man environ
)。
$ ALICE="Alice"; export BOB="Bob"; env | grep "ALICE\|BOB"
BOB=Bob
それで、今、それは夏の太陽と同じくらい明確になるはずです! Brain Agnew、alexp、およびWilliam Prusellに感謝します。
export
は、現在のシェルから分岐したすべてのシェルで変数を使用できるようにします。
変数をエクスポートして後で値を変更できることに注意してください。変数の変更された値は子プロセスで利用可能になります。エクスポート用の変数が設定されたら、export -n <var>
を実行してプロパティを削除する必要があります。
$ K=1
$ export K
$ K=2
$ bash -c 'echo ${K-unset}'
2
$ export -n K
$ bash -c 'echo ${K-unset}'
unset
ご存知かもしれませんが、UNIXでは、プロセスは一連の環境変数(キーと値のペア、キーと値の両方が文字列)を持つことができます。オペレーティングシステムは、プロセスごとにこれらのペアを個別に管理します。
プログラムは、このUNIX APIを介してその環境変数にアクセスできます。
char *getenv(const char *name);
int setenv(const char *name, const char *value, int override);
int unsetenv(const char *name);
プロセスは親プロセスから環境変数も継承します。オペレーティングシステムは、子プロセスが作成された瞬間にすべての「環境」のコピーを作成する責任があります。
Bash は、他のシェルの中でも、ユーザーの要求に応じて環境変数を設定できます。これがexport
が存在するものです。
export
は、Bashの環境変数を設定するためのBashコマンドです。このコマンドで設定されたすべての変数は、このBashが作成するすべてのプロセスによって継承されます。
Bashの環境 の詳細
Bashのもう一つの種類の変数は内部変数です。 Bashは単なる対話型のシェルではないので、実際にはスクリプトインタプリタです。他のインタプリタ(Pythonなど)と同様に、独自の変数セットを保持することができます。 Bashは(Pythonとは異なり)文字列変数のみをサポートすることに注意してください。
Bash変数を定義するための表記法はname=value
です。これらの変数はBash内部に留まり、オペレーティングシステムによって保持されている環境変数とは無関係です。
シェルパラメータの詳細 (変数を含む)
Bashのリファレンスマニュアルによると、これも注目に値する。
シェルパラメータ で説明されているように、単純なコマンドや関数の環境は、パラメータ割り当てを接頭辞として追加することで一時的に増強することができます。これらの代入文は、そのコマンドから見た環境にのみ影響します。
まとめると、
export
は、オペレーティングシステムで環境変数を設定するために使用されます。この変数は、それ以降、現在のBashプロセスによって作成されたすべての子プロセスで利用可能になります。受け入れられた答え はこれを暗示しているが、私はシェル組み込みへの接続を明示的にしたいと思う。
既に述べたように、export
はシェルと子の両方に変数を利用可能にします。 export
がnotを使用している場合、変数はシェル内でのみ使用可能になり、シェル組み込みのみがアクセスできます。
あれは、
tango=3
env | grep tango # prints nothing, since env is a child process
set | grep tango # prints tango=3 - "type set" shows `set` is a Shell builtin
これはまた別の例です。
VARTEST="value of VARTEST"
#export VARTEST="value of VARTEST"
Sudo env | grep -i vartest
Sudo echo ${Sudo_USER} ${Sudo_UID}:${Sudo_GID} "${VARTEST}"
Sudo bash -c 'echo ${Sudo_USER} ${Sudo_UID}:${Sudo_GID} "${VARTEST}"'
Export VARTESTを使用することによってのみ、VARTESTの値がSudo bash -c '...'で使用可能になります。
さらなる例については、以下を参照してください。
bash-hackers.org/wiki/doku.php/scripting/processtree
エクスポートされた変数が環境内にあるか(env)、エクスポートされていない変数が環境内にないかの違いを示すためだけに、
私がこれをするならば:
$ MYNAME=Fred
$ export OURNAME=Jim
環境変数には$ OURNAMEのみが表示されます。変数$ MYNAMEが環境変数にありません。
$ env | grep NAME
OURNAME=Jim
しかし、変数$ MYNAMEはシェルに存在します。
$ echo $MYNAME
Fred
UNIXの2人の作者、Brian KernighanとRob Pikeは、これを彼らの本 "The UNIX Programming Environment"で説明しています。 Googleはタイトルのためにあなたは簡単にpdfバージョンを見つけるでしょう。
それらはセクション3.6のシェル変数を扱い、そのセクションの最後にあるexport
コマンドの使用に焦点を当てます。
サブシェル内で変数の値をアクセス可能にする場合は、シェルのexportコマンドを使用する必要があります。 (あなたはなぜサブシェルからその親に変数の値をエクスポートする方法がないのかについて考えるかもしれません)。
説明では明示的に言及されていませんが、すべての変数が子プロセスにコピーされるので、bashの内側からサブシェルを生成するときにexportを使用する必要はありません。
デフォルトでは、スクリプト内で作成された変数は現在のシェルでしか利用できません。子プロセス(サブシェル)は、設定または変更された値にアクセスできません。子プロセスが値を参照できるようにするには、exportコマンドを使用する必要があります。