プロセスごとにスコープが設定されます
他の回答者は、シェル変数スコープがプロセスとその子孫に関するものであることを理解するのに役立ちました。
ls
コマンドラインのようにコマンドを入力すると、実際にはプロセスをフォークしてls
プログラムを実行します。新しいプロセスには、親としてシェルがあります。
すべてのプロセスは、子プロセスに渡されない独自の「ローカル」変数を持つことができます。また、「環境」変数を設定することもできます。を使用export
すると、環境変数が作成されます。いずれの場合も、無関係なプロセス(元のプロセスのピア)には変数が表示されません。子プロセスが見るものを制御するだけです。
Aと呼ぶbash
bashシェルがあるとします。これを入力するとexport
、Bと呼ぶ子プロセスbashシェルが作成されます。Aで呼び出したものはすべてBに設定されます。
さて、Bでは、と言いFOO=b
ます。次の2つのいずれかが発生します。
- Bが(Aから)と呼ばれる環境変数を受け取らなかった場合
FOO
、ローカル変数を作成します。Bの子はそれを取得しません(Bが呼び出さない限りexport
)。
- B が(Aから)呼び出された環境変数を受け取った場合、B 自体と、その後分岐したchildrenのためにそれ
FOO
を変更します。Bの子には、Bが割り当てた値が表示されます。ただし、これはAにはまったく影響しません。
ここに簡単なデモがあります。
FOO=a # set "local" environment variable
echo $FOO # 'a'
bash # forks a child process for the new shell
echo $FOO # not set
exit # return to original shell
echo $FOO # still 'a'
export FOO # make FOO an environment variable
bash # fork a new "child" shell
echo $FOO # outputs 'a'
FOO=b # modifies environment (not local) variable
bash # fork "grandchild" shell
echo $FOO # outputs 'b'
exit # back to child shell
exit # back to original shell
echo $FOO # outputs 'a'
これらすべてが私の元の問題を説明しています。GEM_HOME
シェルに設定しましたが、を呼び出すとbundle install
、子プロセスが作成されました。私は使用していなかったためexport
、子プロセスはシェルのを受け取りませんでしたGEM_HOME
。
エクスポート解除
を使用して、変数を「エクスポート解除」できます-変数が子に渡されないようにしexport -n FOO
ます。
export FOO=a # Set environment variable
bash # fork a shell
echo $FOO # outputs 'a'
export -n FOO # remove environment var for children
bash # fork a shell
echo $FOO # Not set
exit # back up a level
echo $FOO # outputs 'a' - still a local variable
FOO=bar
、現在のシェルプロセスの値を設定します。次に(bundle install
)のようなプログラムを実行すると、子プロセスが作成されますが、子プロセスはにアクセスできませんFOO
。しかし、私が言っていた場合export FOO=bar
、子プロセス(およびその子孫)はそれにアクセスできます。そのうちの1つはexport FOO=buzz
、その子孫の値を変更するために、または単にFOO=buzz
自分自身の値を変更するために呼び出すことができます。それは正しいですか?