22

私がする時

$ ps -ef | grep cron

私は得る

root      1036     1  0 Jul28 ?        00:00:00 cron
abc    21025 14334  0 19:15 pts/2    00:00:00 grep --color=auto cron

私の質問は、なぜ 2 行目が表示されるのかということです。私の理解でpsは、プロセスをリストし、リストを にパイプしますgrep。プロセスをリストgrepしている間に実行を開始していないのに、プロセスが o/p にリストされているのはなぜですか?psgrep

関連する 2 番目の質問:

私がする時

$ ps -ef | grep [c]ron

私は得るだけ

root      1036     1  0 Jul28 ?        00:00:00 cron

grep1 回目と 2 回目の実行の違いは何ですか?

4

7 に答える 7

33

コマンドを実行すると:

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 は標準入力で特定のパターンに一致する必要があるものを取得するように記述されているため、最初の質問に対する答えが得られます。

  1. シェルが実行されます:ps -ef;
  2. シェルが実行されます:grep cron;
  3. psデータ(文字列「grep cron」を含む)をに送信しますgrep
  4. grepからの検索パターンSTDINと一致し、渡した「cron」属性のために文字列「grep cron」と一致します。 「cron」文字列と一致するようにgrep指示grepしていますが、「grep cron」はによって返される文字列であるため、一致します。psその時点でgrep実行を開始しました。

実行すると:

ps -ef | grep '[c]ron'

渡された属性は、grep「c」の後に「ron」が続くものと一致するように指示します。最初の例と同様ですが、この場合、次のps理由により、返された一致文字列が壊れます。

  1. シェルが実行されます:ps -ef;
  2. シェルが実行されます:grep [c]ron;
  3. psデータ(文字列を含むgrep [c]ron)をに送信しますgrep
  4. grep"c" の後に "ron" が続く文字列が見つからないため、標準入力からの検索パターンと一致しませんが、"c" の後に "]ron" が続く文字列が見つかりました。

GNUgrepには文字列の一致制限がなく、一部のプラットフォーム (Solaris、HPUX、aix だと思います) では、文字列の制限は「$COLUMN」変数または端末の画面幅によって指定されます。

この長い応答によって、シェル パイプ プロセスが少し明確になることを願っています。

ヒント:

ps -ef | grep cron | grep -v grep
于 2012-03-14T01:49:07.610 に答える
9

シェルは、一連のfork(),pipe()およびexec()呼び出しでパイプラインを構築します。シェルによっては、その一部が最初に構築される場合があります。そのため、開始grepする前にすでに実行されている可能性がありpsます。または、最初に起動したとしても、4k カーネル パイプ バッファーに書き込み、起動してパイプ内のデータの消費を開始するpsまで (プロセス出力の行を出力している間) 最終的にブロックされます。grep後者の場合、psが開始する前に開始および終了できる場合、出力にgrepが表示されない場合がありgrep cronます。この非決定論が働いていることにすでに気づいているかもしれません。

于 2011-08-01T02:24:08.917 に答える
8

あなたのコマンドで

ps -ef | grep 'cron'

Linux は、ps -ef コマンドの前に「grep」コマンドを実行しています。次に、Linux は「ps -ef」の標準出力 (STDOUT) を grep コマンドの標準入力 (STDIN) にマップします。

ps コマンドを実行せず、結果をメモリに保存し、それを grep に渡します。それについて考えてみてください、なぜですか?100 ギガバイトのデータをパイプすることを想像してみてください。

編集 2番目の質問に関して:

grep (およびほとんどの正規表現エンジン) では、ブラケットを指定して、ブラケット内の任意の文字を受け入れることを知らせることができます。したがって、[c] と書くと、任意の文字を受け入れることを意味しますが、c のみが指定されます。同様に、他の文字の組み合わせも可能です。

ps aux | grep cron
root      1079  0.0  0.0  18976  1032 ?        Ss   Mar08   0:00 cron
root     23744  0.0  0.0  14564   900 pts/0    S+   21:13   0:00 grep --color=auto cron

^ 独自のコマンドに「cron」が含まれているため、それ自体が一致します。

ps aux | grep [c]ron
root      1079  0.0  0.0  18976  1032 ?        Ss   Mar08   0:00 cron

cron には ac と「ron」が含まれているため、これは cron に一致します。ただし、リクエストは[c]ronであるため、リクエストと一致しません

c: が含まれている限り、括弧内に好きなものを入れることができます。

ps aux | grep [cbcdefadq]ron
root      1079  0.0  0.0  18976  1032 ?        Ss   Mar08   0:00 cron

ただし、C を削除すると一致しません。「cron」は ac で始まるためです。

ps aux | grep [abedf]ron

^ 結果なし

編集 2

繰り返しになりますが、grep を使用すると、ありとあらゆるクレイジーなことを実行できます。これを行う最初のキャラクターを選ぶことに意味はありません。

ps aux | grep [c][ro][ro][n]
root      1079  0.0  0.0  18976  1032 ?        Ss   Mar08   0:00 cron
于 2012-03-13T01:54:48.690 に答える
3

あなたは次のように書いています:「私の理解では、psはプロセスをリストし、そのリストをgrepにパイプします。psがプロセスをリストしている間、grepは実行を開始していません」。

あなたの理解は間違っています。

それはパイプラインの仕組みではありません。シェルは最初のコマンドを最後まで実行せ、最初のコマンドの出力を記憶してから、そのデータを入力として使用して次のコマンドを実行しますいいえ。代わりに、両方のプロセスが実行され、それらの入出力が接続されます。Ben Jackson が書いたように、プロセスが同時に実行されることを特に保証するものは何もなく、両方のプロセスが非常に短命であり、カーネルが接続を通過する少量のデータを快適に管理できる場合です。その場合、それは本当にあなたが期待するように起こる可能性がありますが、偶然にすぎません. ただし、覚えておくべき概念モデルは、それらが並行して実行されるということです。

公式の情報源が必要な場合は、bash の man ページはどうですか:

  A pipeline is a sequence of one or more commands separated by the character |.  The format for a pipeline is:

         [time [-p]] [ ! ] command [ | command2 ... ]

  The  standard  output  of command is connected via a pipe to the standard input of command2.  This connection is
  performed before any redirections specified by the command (see REDIRECTION below).

  ...

  Each command in a pipeline is executed as a separate process (i.e., in a subshell).

2 番目の質問 (まったく関係ありませんが、申し訳ありません) については、正規表現がどのように機能するかについて説明しているだけです。正規表現cronは string に一致しますcron。正規表現が文字列と一致[c]ronしませ[c]ron。したがって、最初の grep コマンドはプロセス リストに表示されますが、2 番目のコマンドは表示されません。

于 2012-03-15T08:15:10.613 に答える
1

あなたの実際の質問は他の人によって回答されていますが、ヒントを提供します:grepリストされたプロセスを見たくない場合は、次の方法で行うことができます:

$ ps -ef | grep [c]ron
于 2011-08-01T02:26:46.847 に答える
0

pgrepps -ef | grep wordを除外するため、よりも優れている場合がありgrepます。試す

pgrep -f bash
pgrep -lf bash
于 2013-11-25T04:25:31.047 に答える
-3
$ ps -ef | grep cron

Linux シェルは常にコマンドを右から左に実行します。そのため、 ps -ef 実行前に grep cron が既に実行されているため、 o/p show はコマンド自体です。

$ ps -ef | grep [c]ron

しかし、この u では grep ron を指定し、その後に c のみを指定しています。したがって、コマンドには [c]ron があるため、o/p にはコマンド ラインがありません。

于 2013-11-11T19:17:58.363 に答える