バックグラウンドで実行したときに(...)新しいサブプロセスを作成しないのはなぜですか?

バックグラウンドで実行したときに(...)新しいサブプロセスを作成しないのはなぜですか?

コマンドを実行した後

{ sleep 5; } &  

出力はps(出力1)

 PID TTY           TIME CMD
  972 ttys000    0:00.27 -bash
 2556 ttys000    0:00.00 -bash
 2557 ttys000    0:00.00 sleep 5   

同時に

( sleep 5 ) &    

出力psは(出力2)

PID TTY           TIME CMD
 972 ttys000    0:00.28 -bash
2566 ttys000    0:00.00 sleep 5  

(){ sleep 5; } &その結果、サブシェル環境が発生した場合、この場合は分岐したサブプロセスが発生するため、「出力1」が予想され、現在のシェルで実行されるため「出力2」が予想されます。愚かな質問のように思えるかもしれませんが、私はこれらの行動を本当に理解していません。
私がここで何を見逃しているのでしょうか?

答え1

Bashはサブシェルの最後または唯一のコマンドを実行します。そしてexec最適化として安全にそうできると思えば。これにより、これを明確に確認できますpstree

$ pstree $$
bash---pstree
$ ( pstree $$ )
bash---pstree
$ ( pstree $$ ; echo)
bash---bash---pstree

$ 

これは、コマンドが中間シェルなしでコマンド( sleep 5 )としてのみ表示される理由です。sleep上記の最後の例では、echoシェルはpstree完了後に強制的にアクションを実行するため、中間のケースでは実際のシェルを使用でき、結果のシェルはすぐにexecspstreeなので、最初のケースと同じように見えます(標準です)。分岐実行)。多くのシェルがこれを行います。


一方、何もないバックグラウンドで実行するには、新しいプロセスを作成する必要があります。:基本的にこれは「背景」です。中かっこ内のコマンドする通常、現在のシェルで実行されますが、バックグラウンドで実行されている場合、これは発生しません。バックグラウンドコマンドの実行中に親シェルが実行している操作を続行するには、フルシェルを実行する新しいシェルを作成する必要があります{ ... }

$ { pstree $$ ; }
bash---pstree
$ { pstree $$ ; } &
bash---bash---pstree

この場合、他の後続命令があるかどうかには違いはない。Bashはこの動作を文書化します。&:

コマンドが制御演算子 " &"によって終了すると、シェルはサブシェルでコマンドを非同期的に実行します。これをバックグラウンドでコマンドを実行するとします。シェルは、コマンドが完了するのを待たずに状態0(true)を返します。

また、バックグラウンドでこのようなことが起こるのを見ることができます。次の組み込みコマンドread:

$ read &
$ pstree $$
[1] 32394
[1]+  Stopped                 read
$ pstree $$
bash-+-bash
     `-pstree

私の殻は今二つ子:bash実行中であり、readこのpstree出力を印刷するコマンドです。


シェルが追加の最適化を実行し、丸括弧で囲まれたサブシェルに適用されているかのように、後から適用できることは事実ですが、そうでは{ ... }ありません。他の一部のシェルではこれを実行できますが、クイックテストでは見つかりませんでした。これは非常にまれであり、形が異なり、いくつかの奇妙な場合があります。

関連情報