术语表/出问题的时候

僵尸进程

又称:defunct进程、已失效进程

简要回答

僵尸进程是已经运行结束、却仍在进程表中留有条目的进程,原因是它的父进程还没有收取它的退出状态。它不占用CPU,几乎也不占内存。

进程结束时,系统会保留一小条记录,让父进程得知它是如何退出的。正常情况下,父进程会马上读取这条记录,条目随之消失。如果父进程一直不读取,已结束的进程就会作为僵尸进程留在列表中。

少量僵尸进程无害。数量持续增长,则说明父程序有bug。

如何在Mac上找出僵尸进程

在“终端”中运行ps -axo pid,ppid,stat,comm | awk '$3 ~ /^Z/'。每一行都是一个僵尸进程,PPID列显示应对它负责的父进程。

如何清除僵尸进程

僵尸进程无法被杀掉,因为它已经退出了。解决办法在父进程上。退出或重新启动父App,僵尸进程就会交给launchd,由它清理掉。

不要为了清除僵尸进程而退出launchd或其他系统进程。如果父进程是系统进程,重新启动Mac就能清除它们。

如何找到僵尸进程的父进程

在ps的完整命令列中,僵尸进程显示为<defunct>,因为它的程序已经退出了。要处理的是它的父进程。

  1. 运行ps -axo pid,ppid,stat,comm | awk '$3 ~ /^Z/'列出僵尸进程。STAT列中的Z表示僵尸进程。
  2. 记下PPID列中的号码。
  3. 运行ps -p <PPID> -o pid,user,command,查看父进程是哪个程序。
  4. 在活动监视器中,选取“显示”>“所有进程,分层显示”,可以看到同样的父子进程树。
  5. 处理父进程。如果它是你打开的App,就退出并重新打开它。如果它是“终端”中的shell或脚本,就关闭那个窗口或停止脚本。如果它是系统进程,就重新启动Mac。

正常与值得担心

父程序通过wait系列系统调用收取子进程的退出状态。一个程序如果启动了子进程却从不等待它们,就会留下僵尸进程。这是父程序的bug,只有它的开发者才能彻底修复。

短暂看到一个僵尸进程是正常的。它存在于进程退出到父进程读取其退出状态之间,这段时间通常很短。

如果同一个父进程一直留着很多僵尸进程,或者它们的数量在几个小时里不断增长,就值得看一看。要统计数量,运行ps -axo stat | grep -c '^Z'。要查看你Mac上的进程数上限,运行sysctl kern.maxproc kern.maxprocperuid。

僵尸进程、孤儿进程和挂起的进程并不相同

这三个说法常被混淆,而每一种需要不同的解决办法。

  • 僵尸进程已经运行结束,只剩下它在进程表中的条目。
  • 孤儿进程仍在运行,但它的父进程已经退出。macOS会把它交给launchd(PID 1),由launchd成为它的新父进程。
  • 挂起的进程仍在运行,只是卡住了,在活动监视器中常显示为“未响应”。和僵尸进程不同,它可以退出或强制退出。

不要做的事

少量僵尸进程无害,所以没有必要为清除它们去冒险。

  • 不要对僵尸进程的PID运行kill -9。它已经退出了,所以信号不起作用。
  • 不要为了清除僵尸进程而退出launchd或其他系统进程。重新启动能安全地达到同样的效果。
  • 不要在没弄清父进程是什么之前就退出它。如果它是一个打开着文稿的App,先存储你的工作。

常见问题

Mac上的僵尸进程是什么?

它是已经结束、但因为父进程还没收取其退出状态而仍被列出的进程。它不占用CPU。

如何杀掉僵尸进程?

没法直接杀掉它。退出或重新启动它的父进程(见ps输出中的PPID列),僵尸进程就会消失。

僵尸进程有害吗?

少量无害。每个僵尸进程都会占用进程表中的一个位置,所以数量多且不断增长时,最终可能引发问题,也说明父程序有bug。

为什么kill -9清除不了僵尸进程?

僵尸进程并没有在运行,所以信号没有可停止的东西。只有它的父进程收取了它的退出状态,或者父进程退出,它才会消失。

重新启动Mac能清除僵尸进程吗?

能。重新启动会结束所有进程,包括僵尸进程及其父进程。

僵尸进程是恶意软件的迹象吗?

不是。它们是Unix进程退出过程中的正常现象。同一个父进程留下很多僵尸进程,通常说明那个程序有bug。

相关条目

从Windows转过来? 请看Mac上的任务管理器,或者最好用的活动监视器替代品。也可以浏览术语表中的所有条目。