如果ps awx | grep -v grep
运行该命令,则会产生以下输出。下面的列表是完整输出的最后 20 行。
4247 pts/1 Ss+ 0:00 /bin/bash
4442 ? S< 0:00 [kworker/u17:1]
4661 ? S< 0:00 [kworker/u17:3]
4731 ? S< 0:00 [kworker/u17:5]
4734 ? S 0:00 pickup -l -t fifo -u
4847 ? S< 0:00 [kworker/u17:7]
4850 ? S 0:00 [kworker/u16:3]
4878 ? S 0:00 [kworker/u16:0]
5201 ? S< 0:00 [kworker/u17:8]
5353 ? S 0:00 [kworker/0:1]
5354 ? S 0:00 [kworker/7:2]
5355 ? S 0:00 [kworker/u16:2]
5361 ? S 0:00 [kworker/4:0]
5362 tty1 Ss 0:00 -bash
5396 ? S 0:00 [kworker/6:0]
5418 ? S 0:00 [kworker/0:0]
5420 ? S 0:00 [kworker/2:2]
5431 ? S 0:00 [kworker/7:0]
5562 ? S 0:00 [kworker/4:2]
5620 tty1 R+ 0:00 ps awx
ps awx | grep grep
如果运行后续命令,则会生成以下输出。
5646 tty1 S+ 0:00 grep --color=auto grep
此外,如果运行以下命令ps awx | grep agetty
,则会显示以下输出。
5669 tty1 S+ 0:00 grep --color=auto agetty
为什么该命令ps awx
不显示进程标识号 5646 和 5669?事实上5620之后没有列出其他进程。
答案1
为什么命令 ps awx 不显示进程标识号 5646 和 5669?
因为你只是5646
作为命令的一部分开始的ps awx | grep grep
,并且5669
作为ps awx | grep agetty
命令的一部分。它们是在最初的列表之后开始的,因此在列表中不可见。两者都会运行,直到处理完ps
该特定管道中进程的输入,因此它们在以后的任何列表中也不会可见。
同样,如果您ps
重复运行,您将看到进程 ID 发生变化:每次运行该命令时,都会启动一个新进程。
更具体地说,所讨论的第二个过程是这样的:
5669 tty1 S+ 0:00 grep --color=auto agetty
这是grep
,其中已经给出了参数--color=auto
和agetty
。这与grep
中的命令匹配ps awx | grep agetty
,该--color=auto
标志可能来自某个别名。这不是一个agetty
过程。其中一个可能会将agetty
或/sbin/agetty
作为命令行的第一部分,如 Debian 系统中的示例所示:
1269 tty3 Ss+ 0:00 /sbin/agetty --noclear tty3 linux
答案2
进程可以通过内核在微秒内来来去去fork()
,无论是在内核内部还是外部。事实上,引用迈克尔·福卡拉基斯:
PID 在用户空间中不按顺序出现的原因是因为内核调度可能会在进程的 fork() 调用之间分叉一个进程。事实上,这很常见。
所以中间ps awx | grep -v grep
发生ps awx | grep grep
了很多事情。有新的进程和线程——它们在ps
捕获它们之前就退出了。您的最后一个示例中也出现相同的逻辑ps awx | grep grep
。但还要注意,grep
PID 实际上可能不是最新的,因为 吉尔斯在相关答案中指出:
[p]iped 命令同时运行。当你运行 ps | grep …,ps 或 grep 是否先启动,以及无论如何它们都会继续,这取决于运气(或者是 shell 工作细节与内核内部调度程序微调相结合的问题)并发执行。
另请注意,其grep -v grep
目的是从ps
输出中删除自身(通常实际上建议| grep -v [g]rep
在这种情况下使用,请参阅相关帖子)。