GNU/Linux >> Linux の 問題 >  >> Linux

括弧は本当にコマンドをサブシェルに入れますか?

私が読んだことから、コマンドを括弧で囲むと、スクリプトの実行と同様に、サブシェルでコマンドを実行する必要があります。これが当てはまる場合、xがエクスポートされていない場合、変数xはどのように表示されますか?

x=1

(echo $x)を実行しています コマンドラインで1

になります

echo $xを実行しています スクリプトでは、期待どおりに何も起こりません

承認された回答:

サブシェルは、元のシェルプロセスのほぼ同一のコピーとして始まります。内部では、シェルはforkを呼び出します システムコール。コードとメモリがコピーである新しいプロセスを作成します。サブシェルが作成されるとき、サブシェルとその親の間にほとんど違いはありません。特に、それらは同じ変数を持っています。 $$でさえ 特殊変数は、サブシェルで同じ値を保持します。これは、元のシェルのプロセスIDです。同様に$PPID 元のシェルの親のPIDです。

いくつかのシェルは、サブシェルのいくつかの変数を変更します。 BashはBASHPIDを設定します サブシェルで変更されるシェルプロセスのPIDに。 Bash、zsh、およびmkshは、$RANDOMを手配します 親とサブシェルで異なる値を生成します。ただし、このような組み込みの特殊なケースを除いて、すべての変数は、サブシェルで元のシェルと同じ値、同じエクスポートステータス、同じ読み取り専用ステータスなどを持ちます。すべての関数定義、エイリアス定義、シェルオプション、および他の設定も継承されます。

(…)によって作成されたサブシェル 作成者と同じファイル記述子があります。サブシェルを作成する他のいくつかの手段は、ユーザーコードを実行する前にいくつかのファイル記述子を変更します。たとえば、パイプの左側はサブシェル内を走り、標準出力がパイプに接続されています。サブシェルも同じ現在のディレクトリ、同じシグナルマスクなどで始まります。いくつかの例外の1つは、サブシェルがカスタムトラップを継承しないことです:無視されたシグナル(trap '' SIGNAL )サブシェルでは無視されたままですが、他のトラップ(trap CODE SIGNAL )デフォルトのアクションにリセットされます。

したがって、サブシェルはスクリプトの実行とは異なります。スクリプトは別のプログラムです。この別個のプログラムは、偶然にも親と同じインタプリタによって実行されるスクリプトである可能性がありますが、この偶然は、別個のプログラムに親の内部データに関する特別な可視性を与えるものではありません。エクスポートされない変数は内部データであるため、子シェルスクリプトのインタープリターが実行されると、これらの変数は表示されません。エクスポートされた変数、つまり環境変数は、実行されたプログラムに送信されます。

したがって:

x=1
(echo $x)

1を出力します サブシェルは、それを生成したシェルの複製であるためです。

x=1
sh -c 'echo $x'

たまたまシェルの子プロセスとしてシェルを実行しますが、x 2行目はxとの接続がありません 2行目よりも

x=1
perl -le 'print $x'

または

x=1
python -c 'print x'

例外はksh93です フォークが最適化され、その副作用のほとんどがエミュレートされるシェル。
意味的には、それらはコピーです。実装の観点からは、多くの共有が行われています。
右側は、シェルによって異なります。
これをテストする場合は、$(trap)などに注意してください。 元のシェルのトラップを報告する場合があります。また、多くのシェルには、トラップを含むコーナーケースにバグがあることにも注意してください。たとえば、ninjaljは、bash 4.3の時点で、bash -x -c 'trap "echo ERR at $BASH_SUBSHELL $BASHPID" ERR; set -E; false; echo one subshell; (false); echo two subshells; ( (false) )' ERRを実行します 「2つのサブシェル」の場合はネストされたサブシェルからトラップしますが、ERRはトラップしません 中間サブシェルからのトラップ— set -E オプションはERRを伝播する必要があります すべてのサブシェルにトラップしますが、中間のサブシェルは最適化されていないため、ERRを実行するためにそこにありません トラップ。

関連:Linux –setuidが機能しないのはなぜですか??
Linux
  1. Linuxlsコマンドをマスターする

  2. シェルコマンドの出力をループするにはどうすればよいですか?

  3. 構文 |&はシェル言語で何を意味しますか?

  1. Linuxシェルのコマンドラインエイリアス

  2. コマンドの出力をシェル変数に割り当てる方法は?

  3. シェルスクリプト内から passwd コマンドを使用する

  1. コンテナー内で docker-compose コマンドからシェル スクリプトを実行します。

  2. bashの&>と>&の違いは何ですか?

  3. シェルから Vim コマンドを実行するには?