Linux 如何杀死多处理模块创建的僵尸进程?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19322129/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to kill zombie processes created by multiprocessing module?
提问by Vor
I'm very new to multiprocessing
module. And I just tried to create the following: I have one process that's job is to get message from RabbitMQ and pass it to internal queue (multiprocessing.Queue
). Then what I want to do is : spawn a process when new message comes in. It works, but after the job is finished it leaves a zombie process not terminated by it's parent. Here is my code:
我对multiprocessing
模块很陌生。我只是尝试创建以下内容:我有一个进程的工作是从 RabbitMQ 获取消息并将其传递给内部队列 ( multiprocessing.Queue
)。然后我想要做的是:当新消息进来时产生一个进程。它可以工作,但在工作完成后,它会留下一个僵尸进程,而不是被它的父进程终止。这是我的代码:
Main Process:
主要流程:
#!/usr/bin/env python
import multiprocessing
import logging
import consumer
import producer
import worker
import time
import base
conf = base.get_settings()
logger = base.logger(identity='launcher')
request_order_q = multiprocessing.Queue()
result_order_q = multiprocessing.Queue()
request_status_q = multiprocessing.Queue()
result_status_q = multiprocessing.Queue()
CONSUMER_KEYS = [{'queue':'product.order',
'routing_key':'product.order',
'internal_q':request_order_q}]
# {'queue':'product.status',
# 'routing_key':'product.status',
# 'internal_q':request_status_q}]
def main():
# Launch consumers
for key in CONSUMER_KEYS:
cons = consumer.RabbitConsumer(rabbit_q=key['queue'],
routing_key=key['routing_key'],
internal_q=key['internal_q'])
cons.start()
# Check reques_order_q if not empty spaw a process and process message
while True:
time.sleep(0.5)
if not request_order_q.empty():
handler = worker.Worker(request_order_q.get())
logger.info('Launching Worker')
handler.start()
if __name__ == "__main__":
main()
And here is my Worker:
这是我的工人:
import multiprocessing
import sys
import time
import base
conf = base.get_settings()
logger = base.logger(identity='worker')
class Worker(multiprocessing.Process):
def __init__(self, msg):
super(Worker, self).__init__()
self.msg = msg
self.daemon = True
def run(self):
logger.info('%s' % self.msg)
time.sleep(10)
sys.exit(1)
So after all the messages gets processed I can see processes with ps aux
command. But I would really like them to be terminated once finished.
Thanks.
因此,在处理完所有消息后,我可以使用ps aux
命令查看进程。但我真的希望他们在完成后被终止。谢谢。
采纳答案by Markku K.
A couple of things:
几件事:
Make sure the parent
joins
its children, to avoid zombies. See Python Multiprocessing Kill ProcessesYou can check whether a child is still running with the
is_alive()
member function. See http://docs.python.org/2/library/multiprocessing.html#multiprocessing.Process
确保父母
joins
是孩子,以避免僵尸。请参阅Python 多处理终止进程您可以检查孩子是否仍在使用
is_alive()
成员函数运行。请参阅http://docs.python.org/2/library/multiprocessing.html#multiprocessing.Process
回答by Al Conrad
Use active_children. multiprocessing.active_children
使用 active_children。 multiprocessing.active_children
回答by Ioannis Filippidis
Using multiprocessing.active_children
is better than Process.join
. The function active_children
cleans any zombies created since the last call to active_children
. The method join
awaits the selected process. During that time, other processes can terminate and become zombies, but the parent process will not notice, until the awaited method is joined. To see this in action:
使用multiprocessing.active_children
比Process.join
. 该函数active_children
清除自上次调用以来创建的所有僵尸active_children
。该方法join
等待选定的进程。在此期间,其他进程可以终止并成为僵尸进程,但父进程不会注意到,直到加入等待的方法。要查看此操作:
import multiprocessing as mp
import time
def main():
n = 3
c = list()
for i in xrange(n):
d = dict(i=i)
p = mp.Process(target=count, kwargs=d)
p.start()
c.append(p)
for p in reversed(c):
p.join()
print('joined')
def count(i):
print('{i} going to sleep'.format(i=i))
time.sleep(i * 10)
print('{i} woke up'.format(i=i))
if __name__ == '__main__':
main()
The above will create 3 processes that terminate 10 second apart each. As the code is, the last process is joined first, so the other two, which terminated earlier, will be zombies for 20 seconds. You can see them with:
以上将创建 3 个进程,每个进程终止 10 秒。如代码所示,最后一个进程首先加入,因此其他两个提前终止的进程将在 20 秒内成为僵尸进程。您可以通过以下方式查看它们:
ps aux | grep Z
There will be no zombies if the processes are awaited in the sequence that they will terminate. Remove the reversed
to see this case. However, in real applications we rarely know the sequence that children will terminate, so using join
will result in some zombies.
如果进程按照它们将要终止的顺序等待,则不会有僵尸。删除reversed
以查看此案例。但是,在实际应用中,我们很少知道子进程将终止的序列,因此使用join
会导致一些僵尸。
The alternative active_children
does not leave any zombies.
In the above example, replace the loop for p in reversed(c):
with:
替代方案active_children
不会留下任何僵尸。在上面的示例中,将循环替换为for p in reversed(c):
:
while True:
time.sleep(1)
if not mp.active_children():
break
and see what happens.
看看会发生什么。