我有一个烦人的僵尸进程,它被 init 收养,而且它不会消失。我读到有一种方法可以创建一个虚拟进程,将僵尸进程附加为该新进程的子进程,然后然后杀死它,将其从进程表中删除。
我究竟该如何做呢?
是的,我已经阅读了大部分内容:
僵尸进程已经死亡,因此无法被杀死。
或者
你应该重新启动系统
和
僵尸进程不使用任何资源,你应该让它们
不幸的是,许多程序会检查进程表来查看实例是否已在运行,如果进程表中有条目,则会拒绝启动新实例。
每次我的 SSHFS 连接断开时,我都会重新启动,并带走 Sublime,这有点愚蠢。
答案1
这仅有的摆脱僵尸进程的一种方法就是让它的父进程报告其退出状态。如果父进程写得正确,wait()
您可以通过将其发送给父进程来实现这一点。SIGCHLD
如果你有僵尸,这通常意味着父母是不是写得正确(因为子进程SIGCHLD
在死亡并成为僵尸进程时已经发送给了它的父进程),所以下一步是杀死父进程。类似(带有选项)
的工具可以显示僵尸进程的谱系,以便您知道哪个进程是父进程。 当父进程死亡时,僵尸进程将被收养,它总是等待子进程死亡,并会愉快地杀死它收养的所有僵尸进程。pstree
-p
init
wait()
如果父进程实际上已经是init
(PID 1),那么您将处于一种不应该发生的情况。您可以尝试发送SIGCHLD
到init
,但您真的不应该这样做,如果这不起作用,您唯一的办法就是重新启动,因为您的系统init
已损坏并且无法正常工作。
(这些是“散弹枪”选项。)
一些比我更有创造力的人如果您想避免终止父进程,也可以使用此选项:
- 确定僵尸进程和父进程的 PID
(在这个例子中,假设僵尸进程的 PID 为 3101,父进程的 PID 为 3100) - 启动
gdb
并attach
返回到父级:
attach 3100
- 呼唤
waitpid
僵尸:
call waitpid(3101,0,0)
- 与父级分离(
detach
)并退出调试器。
(这是一把经过精心调校的狙击步枪。)
答案2
为什么担心僵尸进程?它们占用的资源很少(用于骨架结构任务的空间、PID 和其他东西)。当然,这不太妥当,但就是这样。搜索它们的父进程并修复它们,用更好的替代方法替换它们(可能会有其他有益的副作用),将其报告为错误(它们肯定是)。