当你执行命令时:
ps -ef | grep cron
你正在使用的外壳
(...我假设你的情况是 bash,由于 grep 的颜色属性,我认为你正在运行一个像 linux 发行版这样的 gnu 系统,但它在其他 unix/shell 上也是一样的......)
将执行pipe() 调用来创建一个FIFO,然后它会fork()(创建一个自身的运行副本)。这将创建一个新的子进程。这个新生成的子进程将close() 其标准输出文件描述符(fd 1)并将fd 1 附加到由父进程(执行命令的shell)创建的管道的写入端。这是可能的,因为fork() 系统调用将为每个维护一个有效的打开文件描述符(在本例中为管道 fd)。这样做之后,它将exec() 第一个(在您的情况下)ps 命令在您的PATH 环境变量中找到。通过exec() 调用,该进程将成为您执行的命令。
因此,您现在拥有一个带有子进程的 shell 进程,在您的情况下,它是具有 -ef 属性的 ps 命令。
此时,父(shell)fork()s 再次出现。这个新生成的子进程close()s 它的标准输入文件描述符 (fd 0) 并将 fd 0 附加到由父进程(执行命令的 shell)创建的管道的读取端。
这样做之后,它将在您的 PATH 环境变量中找到exec() 第一个(在您的情况下)grep 命令。
现在您有了带有两个孩子(即兄弟姐妹)的 shell 进程,其中第一个是带有 -ef 属性的 ps 命令,第二个是带有 cron 属性的 grep 命令。管道的读取端附加到grep 命令的STDIN,写入端附加到ps 命令的STDOUT:ps 命令的标准输出附加到grep 命令的标准输入。
由于编写ps 是为了发送每个正在运行的进程的标准输出信息,而编写grep 是为了在其标准输入上获取必须与给定模式匹配的内容,因此您将得到第一个问题的答案:
- shell 运行:
ps -ef;
- shell 运行:
grep cron;
-
ps 将数据(甚至包含字符串“grep cron”)发送到 grep
-
grep 匹配来自STDIN 的搜索模式,并且它匹配字符串“grep cron”,因为您传递给grep 的“cron”属性:您正在指示grep 匹配“cron”字符串并且这是因为“grep cron”是ps 在grep 开始执行时返回的字符串。
当你执行时:
ps -ef | grep '[c]ron'
传递的属性指示grep 匹配包含“c”后跟“ron”的内容。与第一个示例类似,但在这种情况下,它将破坏 ps 返回的匹配字符串,因为:
- shell 运行:
ps -ef;
- shell 运行:
grep [c]ron;
-
ps 将数据(甚至包含字符串grep [c]ron)发送到grep
-
grep 与标准输入中的搜索模式不匹配,因为未找到包含“c”后跟“ron”的字符串,但它找到了包含“c”后跟“]ron”的字符串
GNU grep 没有任何字符串匹配限制,并且在某些平台(我认为是 Solaris、HPUX、aix)上,字符串的限制由“$COLUMN”变量或终端的屏幕宽度给出。
希望这个冗长的响应能够稍微澄清一下 shell 管道过程。
提示:
ps -ef | grep cron | grep -v grep