BashとBourne Shellからコマンドアクションをエクスポートする

BashとBourne Shellからコマンドアクションをエクスポートする

bash v3.2(最新バージョンでも動作すると思いますが):

3.7.4 環境セクションのマニュアルには次のように記載されています。

呼び出されると、シェルは環境をスキャンし、見つかった各名前の引数を生成して自動的に子プロセスにエクスポートできるようにします。

後で付録B Bourne Shellとの主な違いから、マニュアルには次のように記載されています。

シェルの初期環境の変数は自動的に子プロセスにエクスポートされます。 Bourneシェルは通常、エクスポートコマンドを使用して変数を明示的に表示しない限り、この操作は行いません。

これが何を意味するのか分かりません。

以下をcmd1.sh含む

#!/bin/bash

echo yes $ben from cmd1
./cmd2.sh

そしてcmd2.sh含む

#!/bin/bash

echo yes $ben from cmd2

私は最初に文書の意味を理解しました。みんな割り当てられた変数がエクスポートされます(つまり、export変数は必要ありません)。つまり、ランタイム

ben=you;
./cmd1.sh

私はこれが印刷されると予想しました

yes you from cmd1
yes you from cmd2

しかし、代わりに印刷されます。

yes from cmd1
yes from cmd2

したがって、変数がben自動的にエクスポートされないようです。それから私は文書がすべてを意味すると思った環境変数がエクスポートされます(例:ランタイム)。

ben=you;
export ben;
./cmd1.sh

cmd1 は環境変数を受け取るため、bencmd2benで表示されるように自動的にエクスポートされます。つまり、次のものが印刷されると予想しました(実際には次のものが印刷されました)。

yes you from cmd1
yes you from cmd2

しかし、これがBourneシェルと異なるかどうかをテストするために(文書に示されているように)同じコマンドを実行しましたが、代わりに/bin/shshebangを指すように変更し、/bin/bash同じ結果を得ました。つまり、違いはありません。 Bourne シェルでは、次のような出力が出ることが予想されます。

yes you from cmd1
yes from cmd2

エクスポートパラメータを「自動で」表示する方法について話しているときに、ドキュメントで話していることと、これがBourneシェルとどのように異なるかを理解するのに役立つ人はいますか?

いいえ、わかりました。これbashとbourneの動作の間の具体的な違いについて質問がありますが、export関連性がないようです。

答え1

「シェルの初期環境に存在する変数は自動的に子プロセスとしてエクスポートされます。Bourneシェルは、エクスポートコマンドを使用して変数が明示的に表示されない限り、通常これを行いません。」

考慮する:

% export FOO=abc
% bash -c 'FOO=xyz; echo "bash: FOO=$FOO"; echo "env:"; env |grep FOO'
bash: FOO=xyz
env:
FOO=xyz

FOOここでは、対話型シェル(zsh、しかし重要ではない)で設定してエクスポートするように設定しました。次に、環境から変数を受け取り、その値を変更して印刷し、実行するBashを実行しますenv。これは外部コマンドなので、明示的に渡された内部Bash変数のみを表示できます。私たちが見る修正された値はFOOBashの内部で見ることができるので、envBashは環境から変数を取り出し、エクスポートした変数のように渡しました。

引用符で説明されているもう1つの動作は、内部シェルが変数をに渡さないことですenv。次の内容が表示されます。

bash: FOO=xyz
env:

すべての歴史的実装の実際の動作が何であるかわかりません。再現できるのはheirloom-sh(Kusalanandaが言及したのと同じ動作)を使うだけです。オリジナル変数の値が渡されます。

% ./heirloom-sh -c 'FOO=xyz; echo "sh: FOO=$FOO"; echo "env:"; env |grep FOO'
sh: FOO=xyz
env:
FOO=abc

明示的なexport FOO内部シェルも現在の値を渡します。シェルは元の値をFOOスクリプトに表示するため、echo "FOO=$FOO"最初の値も印刷されますFOO=abc

答え2

もともとBourneシェルを使用しないため、Bourneシェルの動作が表示されるとは思わない。 POSIXshシェル(システムでPOSIXモードで実行される1つ以上の他のシェルとして実装されていますbash)は同じように動作し、環境変数に関してBourneシェルの動作はありません。dashbash

などのPOSIXシェルshと、今日のUnixの他のほとんどの一般的なシェルでは、シェルがシェルの親プロセスから継承する環境変数は、シェルで開始されたすべての子プロセスに渡されます。付録のテキストでは、これを「サブプロセスとして自動的にエクスポートした」環境変数と呼びます。bashdash

付録では、これが元のBourneシェルの場合ではなく、子プロセスから継承した環境変数は、export親環境または元のシェルから継承したかどうかにかかわらず、コマンドを使用して明示的にエクスポートする必要があると主張しています。で作成されました。

私が知る限り、元のBourneシェルに最も近いシェルは次のとおりです。/usr/sunos/bin/shソラリスから。これはいコードベースに関する限り、実際には元のBourneシェルですが、長年にわたっていくつかのアップデートがあった可能性があります。

マニュアルによると、このシェルはマニュアルの付録に記載されているとおりに機能しませんbash。それする継承した環境変数を子プロセスに渡します。ただし、継承された環境変数を変更するには、子プロセスで変更された値を表示できるようにその変数をエクスポートする必要があります。

[...]呼び出されると、シェルは環境をスキャンし、見つかった各名前の引数を生成して適切な値を提供します。ユーザーがこれらのパラメーターの値を変更したり新しいパラメーターを作成したりすると、コマンドがシェルのパラメーターをexport環境にバインドするために使用されない限り、これらのパラメーターは環境に影響しません。(また見てくださいset –a)。このコマンドを使用して、環境からパラメータを削除できますunset。したがって、実行されたコマンドに表示される環境は、元のシェルから継承した変更されていない名前と値のペアから削除されたペアを引いたもので構成されますunsetそして、修正や追加があれば、すべてexport注文書に記載する必要があります。

答え3

エクスポートされていない変数は子プロセスの環境にありません。これは、サブシェルの実行時にサブシェルがシェルの初期環境にないことを意味します。

シェルの初期環境に存在する変数は、自動的に子プロセスにエクスポートされます。「は正確ですが、変数が環境にまだ存在していない場合は、そのシェルで使用できないか、サブシェルの子に再エクスポートすることはできません。

これは、エクスポートされていないシェル変数とエクスポートされた環境変数の違いです。シェル変数は現在のシェルに対してローカルであり、エクスポートされた変数は現在のシェル(または他のプログラム)とそのサブルーチンに表示されます。

また、注目すべき点は、子プロセスは親プロセスの環境を変更できないことです。したがって、子プロセスで環境変数を変更しても親プロセスには何の影響もありません。

関連情報