公开学习文档

公开学习文档


ps 问题

<h2>ps 问题</h2> <p>新建测试脚本,名称为 test3.sh,进行如下测试:</p> <pre><code class="language-shell">#!/bin/bash ps auxf | grep test3.sh</code></pre> <p>对于上面方式,主进程为 test3.sh,它会依次 clone 出 2 个子进程并发执行。子进程在稍后会调用 execve 依次将自身替换为 ps 和 grep,但在替换前,子进程是和父进程同名的。</p> <p>由于 2 个子进程是并发执行的,所以在 ps 子进程替换后执行遍历进程时,就存在 2 种可能:</p> <ul> <li> <p>如果 grep 对应的子进程还没有完成替换,此时它的子进程名和父进程是一样的,即是 test3.sh</p> </li> <li>如果已经完成替换,此时子进程的名称就是 grep</li> </ul> <p>&gt; 注意:在比较极端的情况下,grep 对应的子进程甚至还没有来得及创建(或者创建的 pid 号比较小),而 ps 子进程已经替换并执行,此时则根本看不到第 2 个子进程。</p> <p>结果如下:</p> <p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=5f564ec60a36e1804696a0a925cbea62&amp;amp;file=file.png" alt="" /></p> <p>再将脚本内容改为以下:</p> <pre><code class="language-shell">#!/bin/bash PSLIST=`ps auxf | grep test3.sh` echo &amp;quot;${PSLIST}&amp;quot;</code></pre> <p>结果如下:</p> <p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=249794477a0cd5ccdc852e01930daa51&amp;amp;file=file.png" alt="" /></p> <p>这种获取命令输出结果的情况,稍微有些复杂:</p> <ul> <li> <p>如果只有一个命令,则直接起一个子进程,通过 pipe 管道来获取输出</p> </li> <li>如果涉及通过管道连接多个命令,则会新建一个单独的子进程(如图中 7442),再由此子进程再拉 ps 和 grep 进程。</li> </ul> <p>具体可以看下面的常见情况测试总结如下(建议大家用 strace 跟一下流程或看 bash 源码。注意:子进程都是并发执行的):</p> <pre><code class="language-shell"># 没有 pipe,直接起 1 个子进程 ps # 有 1 个 pipe,并起 2 个子进程 ps | grep xxx # 有 2 个 pipe,并起 3 个子进程 ps | grep xxx | grep -v xxx # 有 1 个 pipe,起 1 个子进程 a=`ps` # 有 2 个 pipe,并起 3 个子进程(有个专门的子进程来起 ps, grep 子进程) a=`ps | grep xxx` # 有 3 个 pipe,并起 4 个子进程(同上) a=`ps | grep xxx | grep -v xxx`</code></pre>

页面列表

ITEM_HTML