长时间运行的bash脚本导致可用PID的资源泄漏

长时间运行的bash脚本导致可用PID的资源泄漏,bash,scripting,memory-leaks,Bash,Scripting,Memory Leaks,我目前正在阅读有关Bash脚本的更多细节,尤其是进程管理。在“PIDs和家长”一节中,我发现了以下陈述: 在父进程等待PID查看它是否结束并检索其退出代码之前,进程的PID永远不会在进程死亡后释放以供使用 因此,如果我正确理解了这一点,如果我在bash脚本中启动一个进程,那么该进程将终止,PID不能被任何其他进程使用。这是否意味着,如果我有一个长时间运行的脚本,它反复启动其他子进程,但从不等待它们,那么我最终会有一个资源泄漏,因为使用过的PID不会返回到系统 如果我真的等待另一个进程,但是等待被

我目前正在阅读有关Bash脚本的更多细节,尤其是进程管理。在“PIDs和家长”一节中,我发现了以下陈述:

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

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


如果我真的等待另一个进程,但是等待被陷阱取消了,怎么样。这样的等待是否仍会释放PID,还是陷阱被捕获后我必须再次等待?

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

您可以看到,在6秒以上之后,您没有收到(泄漏的PID)。要查看某些僵尸,请使用以下python代码(再次使用Ctrl+C):

6秒钟后,您将看到一个僵尸:

ps xaw | grep 'sleep'
...
26470 pts/2    Z+     0:00 [sleep] <defunct>
...
ps xaw | grep“睡眠”
...
26470分/2 Z+0:00[睡眠]
...
我的猜测是,bash使用内置wait命令或不使用内置wait命令执行并存储僵尸进程的结果。对于python脚本,如果删除
pl.append
部分,垃圾收集将释放对象,并再次发挥神奇的作用,收获僵尸。仅供参考,一个孩子可能永远不会变成僵尸(来自维基百科,):

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


您不必显式地等待前台进程,因为脚本所在的shell正在等待它们。直到前一个过程完成,下一个过程才会开始


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

当然,当我在前台启动进程时,shell会自动等待,没有问题,所以这个问题当然没有意义。但我指的是后台进程,因为这就是内置的
wait
的目的。@LiKao:如果后台进程完成,它的PID将再次可用,就像它是前台进程一样。只有尚未完成的进程才会占用PID。嗯,那么现在我完全搞不清楚所谓的“僵尸进程”(如上所述,感谢您的提示)是什么,它来自哪里。我自己用一个小脚本(
sleep 10&read
)尝试了一下,一旦睡眠终止,它仍然会被
ps
显示为一个不存在的进程。那么,什么时候以及如何才能真正清除它呢?@LiKao:在我的系统中,
睡眠
一旦完成就不再出现在进程列表中,而
读取
将使脚本处于运行状态。好吧,那么现在我完全困惑了。我想我必须在周末对Unix中的进程和进程处理做一些非常透彻的阅读,然后再回到这个问题上。在我的系统中,我可以清楚地看到睡眠,即使在我等了几分钟之后。也许有一些配置设置了如何处理这个问题。是的,当然,如果您在运行的脚本中按ctrl-c键,子进程将被传递到init进程,然后它将正确地
等待
,从而重新捕获僵尸。但问题是关于一个持续运行很长时间的脚本。我认为维基百科的文章也同意这是一种不好的行为,可能会耗尽进程id池。(“父节点可以通过执行wait系统调用读取子节点的退出状态,然后移除僵尸。”)。不过,我仍然需要弄清楚取消等待的部分。在按下
Ctrl+C
之前,你会看到僵尸,而不是之后
Ctrl+C
只是在完成测试后停止脚本的方法。这6秒只是最短时间,请等待一分钟并检查,然后使用
Ctrl+C
终止。AFAIR僵尸被传递到你的终端(bash/zsh),然后传递到它的父级,依此类推,最后传递到init。在这种情况下,长时间运行的脚本会在不断启动新作业并且从不等待它们时创建僵尸。不,你不会(我没有)。您可以从python脚本中看到它们。python脚本的全部目的是演示如何检查僵尸。bash脚本没有显示任何僵尸。你看到shell(bash)脚本中的僵尸了吗?在我尝试过的系统上,我确实看到了僵尸。一个同事没有。另外,使用
sleep 10&read
的测试对我(即创建的僵尸)有效,但对下面的丹尼斯无效。我现在有了一个新的系统,这里的两个例子都没有创建僵尸,所以我真的猜测其中涉及到一些配置/版本等。不幸的是,我无法再访问旧系统,因此无法检查配置中的差异。我会再贴一张便条,以防我再次找到一个有这种行为的系统,并找出它们之间的区别。
#!/usr/bin/python
import subprocess, time

pl = []
while True:
    pl.append(subprocess.Popen(["sleep", "5"]))
    time.sleep(1)
ps xaw | grep 'sleep'
...
26470 pts/2    Z+     0:00 [sleep] <defunct>
...