在 OS X 10.7 上强制清理 Java 僵尸进程

在 OS X 10.7 上强制清理 Java 僵尸进程

我在 MacBook Pro 上运行了 CrashPlan,但它出了点问题。本质上,它导致了一次 fork 炸弹。幸运的是,我打开了一个终端窗口,可以运行以下命令:

sudo launchctl unload /Library/LaunchDaemons/com.crashplan.engine.plist

因此,不断的重新生成已经停止。但是,我仍然有超过 900 个 Java 进程,它们除了将我的进程数推到最大之外什么也没做。我宁愿不重新启动我的计算机,因为我有很多打开的代码文件、网页等。有没有一种简单的方法可以强制系统收割这些僵尸?我会杀死父进程,但它们都是由 launchd 又名 PID 1 启动的。此时,最好重新启动。

我努力了:

sudo kill -9 <PID>
sudo kill -9 java
sudo killall -9 java    

有没有办法一劳永逸地杀死僵尸,而不必杀死 launchd?还是我必须重新启动才能在这场僵尸大灾难中生存下来?

答案1

僵尸已经死了。不要把它看作是一个进程,而应该把它看作是一个进程槽。没有什么可杀死的,所以 kill -9 和 kill -1 一样有效,意味着什么都没有。

它们正在等待父进程来收割它们。如果父进程因为某种原因没有收割它们,并且父进程没有告诉内核不要生成它们,它们就会变成僵尸进程。

在传统的 UNIX 中,pid 1 是 init,它总是会收获子进程。我认为 launchd 的编码也一样。如果你有 PPID 为 1 的僵尸进程,那么除了重新启动之外,你几乎没有其他选择了。

答案2

不幸的是,没有办法做到这一点。僵尸进程通常是良性的,因为它们的父进程最终会收割它们,而且它们不会消耗资源……但它们确实会影响系统允许的最大进程数(我认为这取决于计算机中安装的 RAM 数量,但我在 Lion 中找不到这方面的文档)。JVM 实例归 launchd(Mac 上的 PID 1)所有,没有安全的方法可以杀死 launchd 并让它重新启动,而不会同时杀死 launchd 的所有子进程。这将是除内核之外的所有内容。

这可能适用于任何失控的 LaunchAgent;这些进程都是 launchd 的子进程,这会带来我遇到的相同问题。我不相信由每段 Java 代码启动的每个 JVM 实例都是由 launchd 生成的,但 CrashPlan 恰好使用 Java,所以我的系统中充斥着这些进程。

我想这里要吸取的教训是:不要使用 fork 炸弹,并随时准备好终端窗口。重新启动后僵尸进程就被清除了,所以一切都很好。

相关内容