サブシェルに変数が表示されるのはなぜですか?

サブシェルに変数が表示されるのはなぜですか?

Learning Bash Bookでは、サブシェルは環境変数やファイル記述子などを継承し、エクスポートしない変数は継承しないと述べています。

$ var=15
$ (echo $var)
15
$ ./file # this file include the same command echo $var

$

私が知る限り、シェルはfor()とforの2つのサブシェルを生成します./file。しかし、この()場合、サブシェルがvar変数をエクスポートしていないにもかかわらず、変数を認識し、その./file場合は認識しません。

# Strace for () 
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f24558b1a10) = 25617
# Strace for ./file
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f24558b1a10) = 25631

strace私はこれがどのように起こったのかを理解しようとしましたが、驚くべきことに、bashはレプリケーションシステムコールに同じ引数を使用することを発見しました。つまり、これはフォークされたプロセスを意味し、親プロセス()./file同じプロセスアドレス空間を持つ必要があります。()この場合、変数はサブシェルに表示されますが、レプリケーション./filesyscallに基づく同じパラメータにもかかわらず同じ状況は発生しませんか?

ベストアンサー1

あなたやこの本は、サブシェルをシェルであるサブプロセスと混同しています。

一部のシェル構成はシェルを生成します。分岐子プロセスLinuxでは、これはforkログで観察されるより一般的なシステムコールの特別なケースです。子プロセスはシェルスクリプトの一部を実行します。子プロセスが呼び出されます。clonestraceサブシェル。最も簡単な設定は次のとおりですcommand1 &command1子シェルで実行し、後続のコマンドは親シェルで実行されます。サブシェルを生成するための他の構成には、コマンドの置き換えと$(command2)パイプcommand3 | command4(ほとんどのシェルcommand3ではサブシェルで実行されますが、command4kshまたはzshでは実行されません)が含まれます。

サブシェルは親プロセスのコピーなので、同じ環境変数だけでなく、変数(元のシェル$$プロセスのプロセスIDを含む)、関数、エイリアス、オプションなどの内部定義も同じです。サブシェルでコードを実行する前に、bashは変数をBASHPIDサブプロセスのプロセスIDに設定します。

これを実行すると外部コマンドが実行されます./file。まず、シェルは子プロセスをフォークしてから、子プロセスをフォークします。実装するexecveシステムコールを介して)実行可能ファイル./file。子プロセスは、親プロセスのプロセス属性(環境、現在のディレクトリなど)を継承します。アプリケーションの内部側面は通話中に失われますexecve。エクスポートされていない変数、関数などはカーネルに未知のbashの概念であり、bashが他のプログラムを実行すると失われます。他のプログラムがbashスクリプトであっても、新しいbashインスタンスによって実行されます。これは、親プロセスもbashインスタンスであるという事実を知らないか気にしません。したがって、シェル変数(エクスポートされていない変数)は生き残ることができませんexecve

おすすめ記事