私はbashのマニュアルを読んでいましたが、次のセクションを見ました。
「コマンド置換、括弧で囲まれたコマンド、および非同期コマンドは、シェル環境と重複するサブシェル環境で呼び出されます。」
私の質問は、サブシェルで何が実行されているのかを実際に見る方法があるかどうかということです。たとえば、私が次の行を書くとしましょう。サブシェルで実行されている内容を実際に表示するにはどうすればよいですか?
$ printf "first\nsecond\nthird" | grep -E "(first|second)"
サブシェルで実際に実行されている内容をどのように確認できますか? 2番目のシェルで「1番目」を把握してから「2番目」を把握することが疑われますが、これが何をしているのか見たいです。
ベストアンサー1
直接見ることはできないと思います。
xtrace
( set -x
) は s とコマンド置換の入れ子レベルを表示しますeval
が、括弧内のグループは表示しません。
Bashはサブプロセスでサブシェルを実行するので、原則としてできるLinuxではsyscallシェルとそのサブプロセスを実行しstrace
たり、同様に見ようとしましたが、出力を解釈するのは少し難しいです。また、このような組み込み機能は呼び出しには表示されず、Bashプロセスは実行するコマンドが1つしかない場合は1レベルの分岐をスキップします。たとえば、外部コマンドは分岐せず、同様にサブシェルと外部コマンドが2つフォークされるのではなく、サブシェルフォークが1つしかありません。fork()
clone()
execve()
printf
execve()
bash -c '/bin/false'
(/bin/false)
$BASHPID
別の場所で印刷して$$
。実行されたコマンドは表示されませんが、これらの印刷物を展開すると少し混乱します。$BASHPID
$$
$ echo $$ >&2; { echo "lhs: $BASHPID" >&2; printf foobar; } | { echo "rhs: $BASHPID" >&2; grep oo; }
30163
rhs: 30166
lhs: 30165
foobar
はい、引用したセクションでは言及していませんが、パイプラインの両方の部分がサブシェルで実行されていることを出力から知ることができます。
とにかく、サブシェルで実行される主な項目は、引用文で述べた3つのパイプです。
非同期/バックグラウンドプロセスは明らかです。シェルと同時に実行されるため、同じプロセスには存在できません。パイプラインのさまざまな部分も同時に実行する必要があるため、最大の基本シェルプロセスで実行できます。 (Bashでは、オプションが設定され、有効な場合は一番右側の部分がこれを行い、lastpipe
そうでない場合は両方とも独自のサブシェル/プロセスを持ちます。)
括弧で囲まれたグループは明示的にサブシェルの使用を要求し、コマンドの置き換えに対する言い訳を思い出さないので、彼らがそうすることを受け入れなければならないようです。
サブシェルの変更は基本シェルに伝播されないため、テストは比較的簡単です。たとえば、次を実行する場合:
bash -c 's=
s+=direct.
(s+=parens.)
$(s+=comsub.)
s+=pipeleft. | s+=piperight.
s+=async. &
eval s+=eval.
echo $s'
あなたは出力を得たdirect.eval.
ので、これは次のようになりますいいえサブシェルで実行します。残りは完了しました。-O lastpipe
以前に追加した場合やスクリプト内で追加した場合は、リストに追加されたものが表示されます-c
。shopt -s lastpipe;
piperight