
吹く組み込み定義ように:
シェルは他のプログラムを呼び出さずに直接コマンドを実行します。
このようなパイプラインはfoo | bar
おおよそ次のように動作します。bar
の入力を待ってfoo
からfoo
終了しますbar
。
Bashでは、これらのパイプラインは期待どおりに機能します。
$ history | grep curl
しかし、タスクが完了し、それ自体で終了することをどのようにgrep
知ることができますか?組み込みプロセスなので、新しいプロセスは作成されませんhistory
。信号を生成history
しますか?history
EOF
答え1
マニュアルに「他のプログラムを呼び出さないでください」と書かれている場合、シェルは他のプログラムをexecve
実行するために使用されないことを意味します。コマンドがリダイレクトを使用する場合、簡単な実装はfork
別のプロセスに移動し、親シェルのファイル記述子を変更せずにそのプロセスのみをリダイレクトすることです。これはbash
このコマンドが実行するアクションであると確認することもできますstrace
。
内部コマンドブランチを回避するために実行できるトリックがいくつかありますが、この場合は使用されないようです。
2番目のプログラムは、1番目のプログラムが終了したことを検出できず、パイプの出力端が閉じていることのみを検出できます(これはプログラムが終了したか一般的なものである可能性がありますclose
)。パイプの読み取り端はEOFを受け取ります。
パイプラインの最初のプログラムが最初に終了するのが一般的ですが、必ずしもそうではありません。考えてみてください:
sleep 10 | echo done
パイプの2番目のプログラムが最初のプログラムの前に終了し、最初のプログラムがパイプに書き込もうとするとシグナルをSIGPIPE
受け取ります。
(sleep 10; echo test ) | echo done