コマンドを実行すると:
ps -ef | grep cron
使用しているシェル
(... grep の color 属性のために、あなたの場合は bash を想定しています。Linux ディストリビューションのような gnu システムを実行していると思いますが、他の unix/shell でも同じです...)
pipe()
FIFO を作成するための呼び出しを実行してから、 fork()
(自身の実行中のコピーを作成します)。これにより、新しい子プロセスが作成されます。この新しく生成された子プロセスはclose()
、その標準出力ファイル記述子 (fd 1) を作成し、親プロセス (コマンドを実行したシェル) によって作成されたパイプの書き込み側に fd 1 をアタッチします。これが可能なのは、fork()
syscall が有効なオープン ファイル記述子 (この場合はパイプ fd) をそれぞれに維持するためです。そうすると、環境変数で見つかっexec()
た最初の(あなたの場合)ps
コマンドになります。PATH
呼び出しによりexec()
、プロセスは実行したコマンドになります。
したがって、子を持つシェルプロセスができました。これは、この場合は属性ps
を持つコマンドです。-ef
この時点で、親 (シェル) はfork()
再び s になります。この新しく生成された子プロセスclose()
は、その標準入力ファイル記述子 (fd 0) を、親プロセス (コマンドを実行したシェル) によって作成されたパイプの読み取り側に fd 0 をアタッチします。
そうすると、PATH環境変数で見つかっexec()
た最初の(あなたの場合)コマンドになります。grep
これで、2 つの子 (兄弟) を持つシェル プロセスができました。最初のプロセスは属性をps
持つコマンドで-ef
、2 つ目のプロセスは属性をgrep
持つコマンドcron
です。パイプの読み取り側はSTDIN
コマンドの にgrep
接続され、書き込み側はコマンドSTDOUT
の に接続されます。ps
コマンドの標準出力は、ps
コマンドの標準入力に接続されgrep
ます。
実行中の各プロセスの標準出力情報を送信するように記述されてps
いるのに対し、grep は標準入力で特定のパターンに一致する必要があるものを取得するように記述されているため、最初の質問に対する答えが得られます。
- シェルが実行されます:
ps -ef;
- シェルが実行されます:
grep cron;
ps
データ(文字列「grep cron」を含む)をに送信しますgrep
grep
からの検索パターンSTDIN
と一致し、渡した「cron」属性のために文字列「grep cron」と一致します。 「cron」文字列と一致するようにgrep
指示grep
していますが、「grep cron」はによって返される文字列であるため、一致します。ps
その時点でgrep
実行を開始しました。
実行すると:
ps -ef | grep '[c]ron'
渡された属性は、grep
「c」の後に「ron」が続くものと一致するように指示します。最初の例と同様ですが、この場合、次のps
理由により、返された一致文字列が壊れます。
- シェルが実行されます:
ps -ef;
- シェルが実行されます:
grep [c]ron;
ps
データ(文字列を含むgrep [c]ron
)をに送信しますgrep
grep
"c" の後に "ron" が続く文字列が見つからないため、標準入力からの検索パターンと一致しませんが、"c" の後に "]ron" が続く文字列が見つかりました。
GNUgrep
には文字列の一致制限がなく、一部のプラットフォーム (Solaris、HPUX、aix だと思います) では、文字列の制限は「$COLUMN」変数または端末の画面幅によって指定されます。
この長い応答によって、シェル パイプ プロセスが少し明確になることを願っています。
ヒント:
ps -ef | grep cron | grep -v grep