僵尸进程
又称:defunct进程、已失效进程
简要回答
僵尸进程是已经运行结束、却仍在进程表中留有条目的进程,原因是它的父进程还没有收取它的退出状态。它不占用CPU,几乎也不占内存。
进程结束时,系统会保留一小条记录,让父进程得知它是如何退出的。正常情况下,父进程会马上读取这条记录,条目随之消失。如果父进程一直不读取,已结束的进程就会作为僵尸进程留在列表中。
少量僵尸进程无害。数量持续增长,则说明父程序有bug。
如何在Mac上找出僵尸进程
在“终端”中运行ps -axo pid,ppid,stat,comm | awk '$3 ~ /^Z/'。每一行都是一个僵尸进程,PPID列显示应对它负责的父进程。
如何清除僵尸进程
僵尸进程无法被杀掉,因为它已经退出了。解决办法在父进程上。退出或重新启动父App,僵尸进程就会交给launchd,由它清理掉。
不要为了清除僵尸进程而退出launchd或其他系统进程。如果父进程是系统进程,重新启动Mac就能清除它们。
如何找到僵尸进程的父进程
在ps的完整命令列中,僵尸进程显示为<defunct>,因为它的程序已经退出了。要处理的是它的父进程。
- 运行
ps -axo pid,ppid,stat,comm | awk '$3 ~ /^Z/'列出僵尸进程。STAT列中的Z表示僵尸进程。 - 记下PPID列中的号码。
- 运行
ps -p <PPID> -o pid,user,command,查看父进程是哪个程序。 - 在活动监视器中,选取“显示”>“所有进程,分层显示”,可以看到同样的父子进程树。
- 处理父进程。如果它是你打开的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上的任务管理器,或者最好用的活动监视器替代品。也可以浏览术语表中的所有条目。