2011-08-01 24 views
12

当我做为什么ps o/p列出管道后的grep进程?

$ 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 

我的问题是,为什么我看到第二行。从我的理解,ps列出的过程和管道列表grepgrep还没有开始,而ps运行的上市进程,那么怎么来grep过程是在O/P上市?

相关的第二个问题:

当我做

$ ps -ef | grep [c]ron 

我只得到

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

是什么第一和第二grep执行之间有什么区别?

+2

你会惊讶于睡眠的结果3 |睡3 |睡3';-) – Alfe

回答

13

当你执行的命令:

ps -ef | grep cron 

您使用

壳(...我假设的bash在你的情况下,由于grep的颜色属性,我想你正在运行一个类似于Linux发行版的gnu系统,但在其他unix/shell上也是如此......)

将执行pipe()调用创建一个FIFO,然后它会fork()(制作一个正在运行的副本)。这将创建一个新的子进程。这个新生成的子进程将其标准输出文件描述符(fd 1)close()并将fd 1附加到父进程(执行该命令的shell所创建的管道的写入端)。这是可能的,因为系统调用将为每个维护有效的打开文件描述符(在这种情况下为管道fd)。这样做之后它会exec()第一个(在你的情况下)ps命令在你的PATH环境变量中找到。通过调用exec(),过程将成为您执行的命令。

所以,你现在有一个孩子的shell进程,在你的情况下,ps命令与-ef属性。

此时,父亲(壳)fork()再次。这个新生成的子进程close()是其标准输入文件描述符(fd 0),并将fd 0附加到由父进程(执行该命令的shell所创建的管道的读取侧)。

这样做会exec()第一(你的情况)在PATH环境变量中找到grep命令后。

现在你有两个孩子(这是兄弟),其中第一个是ps命令-ef属性,第二个是grep命令和cron属性的shell进程。管道的读取端连接到grep命令的STDIN,并且写入端连接到ps命令的:ps命令的标准输出连接到grep命令的标准输入。

由于ps是针对每个正在运行的进程的标准输出信息发送的,而grep是为了获得其标准输入而必须匹配给定模式的东西,所以您将得到第一个问题的答案:

  1. 壳运行:ps -ef;
  2. 壳运行:grep cron;
  3. ps发送数据(即,即使包含字符串 “的grep cron的”)以grep
  4. grepSTDIN的搜索模式匹配,并且由于传递到grep的“cron”属性匹配字符串“grep cron”:您指示grep与“cron”字符串匹配,并且因为“grep cron”是在grep开始执行时由ps返回的字符串。

当你执行:

ps -ef | grep '[c]ron' 

通过属性指示grep匹配含有 “C”,其次是 “罗恩” 的东西。如同第一实施例,但在这种情况下,它会打破由ps因为返回匹配字符串:

  1. 外壳运行:ps -ef;
  2. 外壳运行:rep [c]ron;
  3. ps发送数据(即使包含字符串grep [c]ron)到grep
  4. grep与stdin的搜索模式不匹配,因为包含“c”后跟“ron”的字符串未找到,但找到包含“c”的字符串后跟“] ron”

GNU grep没有任何字符串匹配限制,并且在某些平台上(我认为Solaris,HPUX,aix)字符串的限制是由“$ COLUMN”变量或终端的屏幕宽度给出的。

希望这个长时间的回应澄清了shell管道过程。

提示:

ps -ef | grep cron | grep -v grep 
+0

谢谢你阐述@Ben Jackson的回答。 – abc

6

壳构造的一系列fork()pipe()exec()呼叫您的管道。根据壳,它的任何部分都可以先构建。所以grep可能已经在运行ps甚至开始之前。或者,即使ps开始第一它将被写入4k的内核管缓冲液和最终将阻止(在打印线过程输出的),直到grep启动并开始消耗在管道中的数据。在后一种情况下,如果ps能够开始和结束grep甚至开始你可能看不到grep cron在输出之前。您可能已经注意到这种非确定性。

+0

如果PS块,那么列表将不包含grep..correct。但Ignacio似乎暗示grep必须运行。我有点困惑。 – abc

+0

我其实没有看到你提到的非确定性!但注意到这一点非常有趣。 – abc

1

您的实际问题已经被人回答了,但我会提供一个提示:如果您想避免看到grep上市进程,你可以这样来做:

$ ps -ef | grep [c]ron 
+0

谢谢,但我对下面的答案有进一步的怀疑。请看我的评论。 – abc

+0

为什么使用grep [c] ron没有列出grep进程,而使用grep cron总是列出grep进程?括号表达式的作用是什么?你能否详细说明一下? – abc

+3

@abc它可以工作,因为'grep'正则表达式完全匹配'c'后面跟'ron',但'ps'输出将显示字面意义上的'grep [c] ron',因为那是输入的命令。因此,'grep'的表达式不匹配并将其过滤掉。 –

8

在您的命令

ps -ef | grep 'cron' 

Linux在执行ps -ef命令之前执行“grep”命令。然后,Linux将“ps -ef”的标准输出(STDOUT)映射到grep命令的标准输入(STDIN)。

它不执行ps命令,结果存储在内存中,并把它传递到grep。想想,为什么呢?想象一下,如果你管理的是一百千兆字节的数据?

编辑在关于你的第二个问题:

在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,因为cron的包含了一个C,然后 “罗恩”。这不,虽然符合你的要求,因为你的要求是[C]罗恩

你可以把任何你想要的括号,只要它包含C:

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

如果您删除C ,它虽然不会匹配,因为 “cron的”,开始与交流:

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 
+0

我刚刚在问题中增加了一个部分。我想到很难阅读“赏金笔记”。谢谢。 – abc

+0

Ben Jackson(下图)似乎暗示ps可能会在grep之前运行并将数据写入内核管道。 – abc

+0

据我所知,哪一个先开始是无关紧要的。在PS的STDOUT被映射到GREP的STDIN之前,操作系统不一定分配任何CPU时间给它们中的任何一个。 – GoldenNewby

1

您写道:“从我的理解,PS列出的过程和管道列表中的grep grep的还没有开始,而PS的上市进程在运行。”

你的理解不正确。

这不是管道的工作原理。 shell不会不是运行第一个命令完成,记住第一个命令的输出,然后之后运行下一个命令使用该数据作为输入。没有。相反,均为进程执行并且它们的输入/输出为连接。正如Ben Jackson所写,没有什么特别保证这些进程同时运行,如果它们都很短暂,并且内核可以轻松管理通过连接传递的少量数据。在这种情况下,它确实可能以您期望的方式发生,只是偶然。但要牢记的概念模型是它们并行运行。

如果你想官方消息,怎么样bash手册页:

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). 

至于你的第二个问题(这是不是真的在所有相关的,我很抱歉地说),你是只是描述正则表达式如何工作的一个特征。正则表达式cron与字符串cron匹配。正则表达式[c]ron确实是而不是匹配字符串[c]ron。因此,第一个grep命令将自己找到进程列表中,但第二个不会。

0
$ ps -ef | grep cron 

Linux Shell总是执行从右向左的命令。所以,在ps -ef执行之前,grep cron已经执行了,这就是为什么o/p show是命令本身。

$ ps -ef | grep [c]ron 

但是在这个u指定的grep ron后面只有c。所以,o/p没有命令行,因为命令中有[c] ron。

0

pgrep有时比ps -ef | grep word好,因为它不包括grep。尝试

pgrep -f bash 
pgrep -lf bash 
相关问题