`ps -x | grep foo` に grep コマンドが含まれているのはなぜですか?

`ps -x | grep foo` に grep コマンドが含まれているのはなぜですか?

それは分かっているする(多くの場合) grep プロセスを含め、代わりに追加| grep -v grepまたは grep すると[f]ooそれが防止されることはわかっていますが、私の質問は操作の順序に関するものだと思います。

たとえば、この不自然な例では、いくつかの grep プロセスが見られます。

% ps -x | grep login | grep login | grep login | grep login
 2475 ??         0:00.03 /usr/libexec/loginitemregisterd
 2115 ttys004    0:00.04 login -fp jasonerickson
29715 ttys004    0:00.00 grep login
29716 ttys004    0:00.00 grep login
29717 ttys004    0:00.00 grep login
29718 ttys004    0:00.00 grep login

ps -xそれは実行されなければならないことを私に告げる最後その行には、後続のgrepコマンドがすべてリストされているからです。しかし、一貫性がありません。4つ、3つ、2つ、またはまったくgrepプロセスがリストされないこともあります。これは、いつも最後。

どうしたの?

答え1

Bravo が指摘しているように、Linux のパイプはファイルではなく、動的です。そのため、ps -x | grep login実際には両方のプログラムが同時に起動され、一方がパイプに送り込まれ、もう一方がキャッチできます。これが決定論的ではない理由、つまり、あなたの不自然な例が常に 4 つのgrepインスタンスを示さない理由は、パイプに何か実行する必要があるまでインスタンスが起動されない場合や、プロセス リストを読み取ったときに問題のインスタンスが完全に起動されない場合があるためですps

答え2

Unix はマルチタスク オペレーティング システムです。ps を最初または最後に起動することはありません。パイプライン内のすべてのものを並行して起動します。いくつかは最初に終了するか、ps の起動後に起動する可能性があり、これが競合が発生する原因で、結果がやや非決定的になります。

基本的に、ここでは操作の順序はありません。パイプラインはデータ ストリームであり、数式ではありません。

UNIX のパイプの優れた点は、最初のプログラムが終了する前に 2 番目のプログラムが入力の処理を開始できるため、パイプ内の次のプログラムに渡す前にデータ ストリーム全体をメモリ (またはディスク) に収集して保存する必要がないことです。

関連情報