ps命令显示伪造的子进程

时间:2013-09-05 07:36:55

标签: shell unix process ksh ps

我在unix系统上遇到了一个有趣的问题(在SunOS和AIX上测试过):我执行一个脚本并希望列出自己(使用ps) - 有时ps显示两个,脚本的其他子进程,有时只有一个额外的子进程,大多数情况下输出正确显示单个进程。我在这里发现了一个帖子Multiple processes with the same name,但我的情况有所不同。

考虑一个名为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上的文件系统结构。

1 个答案:

答案 0 :(得分: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调用完成后才会被替换。

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