2

我在 unix 系统上遇到了一个有趣的问题(在 SunOS 和 AIX 上测试):我执行一个脚本并想列出它自己(使用ps) - 有时 ps 显示脚本的两个额外的子进程,有时它只有一个额外的子进程并且大多数时候输出正确地显示了一个进程。我在这里找到了一个线程多个具有相同名称的进程,但我的情况不同。

test.sh考虑一个名为以下的脚本:

#!/bin/ksh
echo before $$
ps -f | grep test.sh | grep -v grep
echo after $$

这很简单——它显示它的 PID,然后在进程列表中找到它自己(等等),并且只过滤掉 grep 命令(以防万一)。现在,我将在 shell 中执行一个非常简单的例程:

while [ 1 -eq 1 ]; do test.sh; done

只是一个一个一个一个执行的无限循环test.sh。我在输出中得到什么?见下文:

before 20990
  user   20990 14993   0 08:54:06 pts/5       0:00 /bin/ksh test.sh
after 20990
before 20994
  user   20994 14993   0 08:54:06 pts/5       0:00 /bin/ksh test.sh
after 20994
before 20998
  user   21001 20998   0 08:54:06 pts/5       0:00 /bin/ksh test.sh
  user   21000 20998   0 08:54:06 pts/5       0:00 /bin/ksh test.sh
  user   20998 14993   0 08:54:06 pts/5       0:00 /bin/ksh test.sh
after 20998
before 21002
  user   21002 14993   0 08:54:06 pts/5       0:00 /bin/ksh test.sh
after 21002
before 21006
  user   21006 14993   0 08:54:07 pts/5       0:00 /bin/ksh test.sh
after 21006

谁能向我解释一下 21001 和 21000 的进程是什么?它们没有分叉,因为它们没有“之前/之后”的痕迹。这种情况只是偶尔发生...

这对我来说不是什么大问题,但我很想知道这里发生了什么以及在更复杂的情况下会发生什么。

假设我只想在没有执行此脚本的其他会话时才允许执行我的脚本。然后,我将使用 ps 并过滤“test.sh”+ 过滤掉我的 PID 的所有行 - 在这里,脚本将过滤掉自身 + 它的子项,这很好,但这只是解决我不知道的问题的方法真不明白。因此这个线程:)

我没有尝试获取存储在 /proc 中的实际数据,因为我不知道 Sun 或 AIX 上的文件系统结构。

4

1 回答 1

1

这些额外的进程是即将处理前两个管道组件的子shell。

这可以通过运行显示所有 exec 调用的 dtrace 脚本来确认:

before 3929
    root  3929  1630   0 10:36:03 pts/3       0:00 /bin/ksh ./test.sh
    root  3932  3929   0 10:36:03 pts/3       0:00 /bin/ksh ./test.sh
    root  3931  3929   0 10:36:03 pts/3       0:00 /bin/ksh ./test.sh
after 3929

这些进程的 dtrace 输出:

2013 Sep  5 10:36:02 3929 /bin/ksh ./test.sh
2013 Sep  5 10:36:02 3931 grep test.sh
2013 Sep  5 10:36:02 3932 grep -v grep

事实/bin/ksh ./test.sh显示而不是实际的命令运行argv[0]尚未更新。只有在 exec 调用完成后才会替换它。

就在分叉之后,父进程和子进程共享相同的参数列表。唯一的区别是进程 ID。这就是你正在观察的。

于 2013-09-05T08:31:10.353 回答