蟒蛇 - 终止子进程时,脚本调用的bash [英] python - terminate child process when script invoked from bash

查看:133
本文介绍了蟒蛇 - 终止子进程时,脚本调用的bash的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个python脚本:zombie.py

I have a python script: zombie.py

from multiprocessing import Process
from time import sleep
import atexit

def foo():
    while True:
        sleep(10)

@atexit.register
def stop_foo():
    p.terminate()
    p.join()

if __name__ == '__main__':
    p = Process(target=foo)
    p.start()

    while True:
        sleep(10)

当我与蟒蛇zombie.py和放大器运行此; 并杀死父进程杀死-2 ,在停止()正确调用和两个进程终止。

When I run this with python zombie.py & and kill the parent process with kill -2, the stop() is correctly called and both processes terminate.

现在,假设我有一个bash脚本zombie.sh:

Now, suppose I have a bash script zombie.sh:

#!/bin/sh

python zombie.py &

echo "done"

和我在命令行中运行 ./ zombie.sh

现在,停止()永远不会当父就会被杀死调用。如果我运行杀-2 父过程中,没有任何反应。 杀-15 杀死-9 均只有杀掉父进程,而不是孩子:

Now, stop() never gets called when the parent gets killed. If I run kill -2 on the parent process, nothing happens. kill -15 or kill -9 both just kill the parent process, but not the child:

[foo@bar ~]$ ./zombie.sh 
done
[foo@bar ~]$ ps -ef | grep zombie | grep -v grep
foo 27220     1  0 17:57 pts/3    00:00:00 python zombie.py
foo 27221 27220  0 17:57 pts/3    00:00:00 python zombie.py
[foo@bar ~]$ kill -2 27220
[foo@bar ~]$ ps -ef | grep zombie | grep -v grep
foo 27220     1  0 17:57 pts/3    00:00:00 python zombie.py
foo 27221 27220  0 17:57 pts/3    00:00:00 python zombie.py
[foo@bar ~]$ kill 27220
[foo@bar ~]$ ps -ef | grep zombie | grep -v grep
foo 27221     1  0 17:57 pts/3    00:00:00 python zombie.py

这是怎么回事?我怎样才能确保子进程与父去世?

What is going on here? How can I make sure the child process dies with the parent?

推荐答案

更​​新:此解决方案不通过信号杀死进程工作

Update: This solution doesn't work for processes killed by a signal.

您的孩子的过程是不是一个僵尸。它是活的。

Your child process is not a zombie. It is alive.

如果你想被杀死子进程时,其父的正常退出的再设置 p.daemon = TRUE p.start()。从的文档

If you want the child process to be killed when its parent exits normally then set p.daemon = True before p.start(). From the docs:

当一个进程退出时,它会试图终止其所有恶魔的子进程。

When a process exits, it attempts to terminate all of its daemonic child processes.

看着源$ C ​​$ C ,很显然,多处理使用 atexit对回调杀人恶魔的其子女即它不会工作,如果母公司是由信号终止。例如:

Looking at the source code, it is clear that multiprocessing uses atexit callback to kill its daemonic children i.e., it won't work if the parent is killed by a signal. For example:

#!/usr/bin/env python
import logging
import os
import signal
import sys
from multiprocessing import Process, log_to_stderr
from threading import Timer
from time import sleep

def foo():
    while True:
        sleep(1)

if __name__ == '__main__':
    log_to_stderr().setLevel(logging.DEBUG)
    p = Process(target=foo)
    p.daemon = True
    p.start()

    # either kill itself or exit normally in 5 seconds
    if '--kill' in sys.argv:
        Timer(5, os.kill, [os.getpid(), signal.SIGTERM]).start()
    else: # exit normally
        sleep(5)

输出


$ python kill-orphan.py
[INFO/Process-1] child process calling self.run()
[INFO/MainProcess] process shutting down
[DEBUG/MainProcess] running all "atexit" finalizers with priority >= 0
[INFO/MainProcess] calling terminate() for daemon Process-1
[INFO/MainProcess] calling join() for process Process-1
[DEBUG/MainProcess] running the remaining "atexit" finalizers

注意的调用终止()进行守护的行。


$ python kill-orphan.py --kill
[INFO/Process-1] child process calling self.run()

该日志表明,如果父母是那么的信号封杀的atexit回调不叫(和 PS 显示,孩子是活在这种情况下)。另请参见多进程守护进程没有结束对家长退出

The log shows that if the parent is killed by a signal then "atexit" callback is not called (and ps shows that the child is alive in this case). See also Multiprocess Daemon Not Terminating on Parent Exit.

这篇关于蟒蛇 - 终止子进程时,脚本调用的bash的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆