回答:
export
変数をサブプロセスで使用できるようにします。
あれは、
export name=value
変数名は、そのシェルプロセスから実行するすべてのプロセスで使用できます。プロセスでこの変数を使用する場合は、を使用してexport
、そのシェルからプロセスを実行します。
name=value
変数のスコープがシェルに制限されており、他のプロセスでは使用できないことを意味します。これを(たとえば)ループ変数、一時変数などに使用します。
変数をエクスポートしても、親プロセスで使用できるようになるわけではないことに注意してください。つまり、生成されたプロセスで変数を指定してエクスポートしても、その変数を起動したプロセスで使用できるようにはなりません。
name=value command
んサブプロセス内の変数を利用できるようにしますcommand
。
他の人は、エクスポートによってサブシェルが変数を使用できるようになると回答しています。これは正しいことですが、単なる副作用です。変数をエクスポートすると、その変数は現在のシェルの環境に配置されます(つまり、シェルはputenv(3)
またはを呼び出しますsetenv(3)
)。
プロセスの環境はexec全体で継承され、変数をサブシェルで表示できます。
編集(5年の視点で):これはばかげた答えです。「エクスポート」の目的は、それらのコマンドがサブシェルであろうとサブプロセスであろうと、変数を「後で実行されるコマンドの環境にある」ようにすることです。素朴な実装は、シェルの環境に変数を配置するだけですが、これは実装を不可能にしますexport -p
です。
bash
、exportは実際に変数を現在のシェルの環境に追加しますが、ではそうではありませんdash
。現在のシェルの環境に変数を追加することが、のセマンティクスを実装する最も簡単な方法であるようにexport
思えますが、その動作は必須ではありません。
dash
が関係しているのかわかりません。オリジナルのポスターは特にについて尋ねていましたbash
。
bash
が付けられていますが、ボーンシェルバリアントにも同様に適用されます。過度に具体的であり、それにのみ当てはまる回答を提供することbash
は、大きな悪です。
bash
シェルのjQueryです。
export makes the variable available to subshells, and that is correct
これは非常に混乱する用語の使い方です。サブシェルはexport
変数を継承する必要はありません。サブプロセスは行います。
サブシェルをスポーンするときにbashでエクスポートする必要はないと言われていますが、反対の意見もあります。それはサブシェルとの違いに注意することが重要である(によって作成されたものを()
、``
、$()
またはループ)とサブプロセス(例えば、名前によって呼び出されたプロセスリテラル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()が続きます。そのため、実際にはexec()であるのに対し、fork()が検索対象であるように見えます。最初にfork()を実行せずにコマンドを実行できます。exec
このメソッドで開始されたプロセスも、エクスポートされていない変数にアクセスできません。
$ noexport=noexport; export export=export; exec bash -c 'echo execd process: $noexport $export; execd=execd'; echo parent: $execd
execd process: export
parent:
今回は親シェルをexec
コマンドに置き換えたため、この行は表示されないことに注意してください。そのため、そのコマンドを実行するために残っているものはありません。
&
)もサブシェルを作成します。
var=asdf bash -c 'echo $var'
どうvar=asdf exec bash -c 'echo $var'
ですか?出力はasdf
です。;
変数定義の後に置かれた場合の違いになります。説明は何でしょうか?それは次のようになりますvar
(なしで;
原点シェルのために何らかの形で生成されたサブプロセスに関して、)それとは何の関係もありません。echo $var
2行目に実行しても何も出力されません。しかし、裏地var=asdf bash -c 'echo $var'; echo $var
が1つありますasdf\nasdf
。
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 -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);
プロセスは、親プロセスから環境変数も継承します。オペレーティングシステムは、子プロセスの作成時にすべての「envars」のコピーを作成する責任があります。
Bashは、他のシェルの中でも、ユーザーの要求に応じて環境変数を設定できます。これがexport
存在する理由です。
export
Bashの環境変数を設定するBashコマンドです。このコマンドで設定されたすべての変数は、このBashが作成するすべてのプロセスに継承されます。
バッシュの環境の詳細
Bashの別の種類の変数は内部変数です。Bashは単なるインタラクティブシェルではないため、実際には他のインタープリター(Pythonなど)と同様にスクリプトインタープリターであり、独自の変数のセットを保持できます。Bashは(Pythonとは異なり)文字列変数のみをサポートしていることに注意してください。
Bash変数を定義するための表記はname=value
です。これらの変数はBash内にとどまり、オペレーティングシステムによって保持される環境変数とは何の関係もありません。
シェルパラメータの詳細(変数を含む)
また、Bashリファレンスマニュアルによると、注目に値します。
シェルパラメータで説明されているように、単純なコマンドまたは関数の環境は、パラメータ割り当てを前に付けることによって一時的に拡張できます。これらの割り当てステートメントは、そのコマンドが認識する環境にのみ影響します。
まとめると:
export
オペレーティングシステムの環境変数を設定するために使用されます。この変数は、現在のBashプロセスによって作成されたすべての子プロセスで使用できます。受け入れられた答えは、このことを意味しますが、私はシェル組み込みコマンドへの明示的な接続をしたいのですが。
すでに述べたようにexport
、シェルと子の両方が変数を使用できるようにします。export
が使用されていない場合、変数はシェルでのみ使用可能であり、シェルのビルトインのみが変数にアクセスできます。
あれは、
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}"'
VARTESTのエクスポートを使用することによってのみ、VARTESTの値をsudo bash -c '...'で使用できます。
その他の例については、以下を参照してください。
bash-hackers.org/wiki/doku.php/scripting/processtree
UNIXの作成者の2人、Brian KernighanとRob Pikeは、彼らの著書「The UNIX Programming Environment」でこれを説明しています。タイトルにGoogleを使用すると、PDFバージョンを簡単に見つけることができます。
それらはセクション3.6でシェル変数を扱い、export
そのセクションの終わりでコマンドの使用に焦点を合わせます:
変数の値をサブシェルでアクセスできるようにするには、シェルのエクスポートコマンドを使用する必要があります。(サブシェルからその親に変数の値をエクスポートする方法がない理由について考えるかもしれません)。
説明では明示的に言及していませんが、すべての変数が子プロセスにコピーされるため、bash内からサブシェルを生成するときにエクスポートを使用する必要はありません。
export name=value
移植性がないことに注意してください。正確に何をしたいかに応じてname=value; export name
、ポータブルソリューションを試してください。