当我检查某些进程时,我通常会写
ps aux | grep myprocess
和有时我得到的输出
eimantas 11998 0.0 0.0 8816 740 pts/0 S+ 07:45 0:00 grep myprocess
如果进程没有运行。
现在我真的想知道为什么 grep 会出现在进程列表中,如果它过滤掉了ps
命令的输出后 ps
已经跑了?
答案1
这种行为是完全正常的,这是由于 bash 管理管道使用的方式造成的。
管道是由 bash 使用以下实现的pipe
系统调用。在该调用之后,bash 分叉并替换标准输入 (文件描述符 0) 与来自正确过程 ( ) 的输入grep
。主 bash 进程创建另一个 fork 并传递 fifo 的输出描述符来代替标准输入(文件描述 1)并启动左侧命令。
该ps
实用程序在命令之后启动grep
,因此您可以在输出中看到它。
如果您不相信它,您可以使用set -x
启用命令跟踪。例如:
+ ps aux
+ grep --color=auto grep
+ grep --color=auto systemd
alexises 1094 0.0 0.8 6212 2196 pts/0 S+ 09:30 0:00 grep --color=auto systemd
有关更多说明,您可以查看基本 c shell 的这部分:http://www.cs.loyola.edu/~jglenn/702/S2005/Examples/dup2.html
答案2
当我只对进程的存在感兴趣时,我使用pgrep
不显示此行为的进程,例如:
$ pgrep myprocess
1900
在其他情况下(当我对更多信息感兴趣时),我通常添加 a| grep -v grep
来丢弃 grep 行,例如:
$ ps -ef | grep myprocess| grep -v grep
答案3
的pipe
行为不像;
.它同时启动这两个进程。这就是该grep
命令也出现的原因。因此,当您给出 时ps aux | grep myprocess
,ps aux
包含了grep myprocess
,因此 grep 将其包含在其输出中。
为了检查这一点,我dd
在测试服务器上发出了两个命令,如下所示:
[sreeraj@server ~]$ dd if=/dev/urandom of=/home/sreeraj/myfile1 bs=1M count=1024 | dd if=/dev/urandom of=/home/sreeraj/myfile2 bs=1M count=1024
当我检查该dd
进程时,它显示两个进程已同时启动(查看显示 2:55 分钟已过去的栏):
[sreeraj@server ~]$ ps aux | grep 'dd if'
sreeraj 14891 100 0.2 5376 1416 pts/0 R+ 11:56 2:55 dd if=/dev/urandom of=/home/sreeraj/myfile1 bs=1M count=1024
sreeraj 14892 100 0.2 5376 1412 pts/0 R+ 11:56 2:55 dd if=/dev/urandom of=/home/sreeraj/myfile2 bs=1M count=1024
sreeraj 14936 0.0 0.1 9032 672 pts/1 S+ 11:59 0:00 grep --color=auto dd if
[sreeraj@server ~]$
现在,如果您想排除 grep 的输出,请使用正则表达式。它将grep
从结果中排除:
ps aux | grep "[m]yprocess"
例如,如果您正在寻找 httpd 进程,请使用:
ps aux | grep "[h]ttpd"
但我建议你使用pgrep -a
,这样会更可靠。
[sreeraj@server ~]$ pgrep -a httpd
8507 /usr/sbin/httpd -DFOREGROUND
8509 /usr/sbin/httpd -DFOREGROUND
8510 /usr/sbin/httpd -DFOREGROUND
8511 /usr/sbin/httpd -DFOREGROUND
8513 /usr/sbin/httpd -DFOREGROUND
8529 /usr/sbin/httpd -DFOREGROUND
[sreeraj@server ~]$
答案4
考虑这个思想实验:如果在您认为应该ps
调用之前运行完成grep
,则意味着 shell 需要:
- 调用
ps
. - 缓冲其所有输出(因为它还没有其他地方可去)。
- 调用
grep
. - 将保存的输出馈送到
grep
sstdin
。
这是浪费;首先调用它是一种更有效的内存使用方式grep
,让它等待输入,然后将ps
sstdout
直接提供给grep
s stdin
。
或者,考虑到极端情况,考虑通过管道传输生成无限量输出的程序的输出的情况,例如:
$ yes | less
如果 shellyes
在 之前运行less
,您将永远等待(或者直到完全耗尽计算机内存)。