2

我目前正在阅读有关 Bash 脚本的更多详细信息,尤其是这里的流程管理。在“PIDs and parents”一节中,我发现了以下声明:

进程死亡后,进程的 PID 将永远不会被释放以供使用,直到父进程等待 PID 查看它是否结束并检索其退出代码。

因此,如果我正确理解这一点,如果我在 bash 脚本中启动一个进程,那么该进程将终止,该 PID 不能被任何其他进程使用。这是否意味着,如果我有一个长时间运行的脚本,它反复启动其他子进程但从不等待它们,我最终会出现资源泄漏,因为使用过的 PID 不会返回给系统?

如果我实际上是wait为了另一个进程,但是waitget 被陷阱取消了,怎么样。这种等待会以某种方式释放PID,还是在捕获陷阱后我必须再次等待?

4

2 回答 2

2

幸运的是你不会。我不能告诉你确切的原因,但你可以很容易地测试它。运行以下脚本(以 停止Ctrl+C):

#!/bin/bash

while true; do
    sleep 5 &
    sleep 1
done

您可以看到6 多秒后没有僵尸(泄漏的 PID)。要查看一些僵尸,请使用以下 python 代码(同样,以 停止Ctrl+C):

#!/usr/bin/python
import subprocess, time

pl = []
while True:
    pl.append(subprocess.Popen(["sleep", "5"]))
    time.sleep(1)

6 秒后你会看到一个僵尸:

ps xaw | grep 'sleep'
...
26470 pts/2    Z+     0:00 [sleep] <defunct>
...

我的猜测是 bash 确实会等待并存储使用或不使用内置等待命令的僵尸进程的结果。对于 python 脚本,如果您删除pl.append垃圾收集的部分,则会释放对象并再次收获僵尸。仅供参考,孩子可能永远不会成为僵尸(来自维基百科,僵尸进程):

...如果父进程通过将其处理程序设置为 SIG_IGN(而不是默认情况下简单地忽略信号)显式忽略 SIGCHLD 或设置了 SA_NOCLDWAIT 标志,则所有子退出状态信息将被丢弃,并且不会留下僵尸进程。

于 2012-06-15T01:20:34.650 回答
0

您不必显式等待前台进程,因为运行脚本的 shell 会等待它们。在前一个过程完成之前,下一个过程不会开始。

如果您启动许多长时间运行的后台进程,您可以使用所有可用的 PID,但这受制于ulimit -u(可能是无限的)的限制。

于 2012-06-15T02:13:17.973 回答