从python / bash中杀死子子进程而不留下孤儿

时间:2016-09-09 22:46:35

标签: python linux bash ubuntu subprocess

我有一个包含3个主要组件的系统(一切都在Ubuntu14.04和Python 2.7上运行,不要太在意可移植性):

a)执行的一些二进制文件,我们将其称为runtime,它将一些值写入{c}需要读取的stdoutstderr

b)设置了环境并执行runtime的启动器脚本,让我们称之为launcher,它看起来像这样:

#!/bin/bash

#Needed by the runtime
export SOME_VAR=1234 
source some_file.sh
#...
exec runtime --option1 $1 --option2 $2

c)服务器,它处理远程请求并在远程客户端请求时调用launcher。服务器是用python编写的,需要从(a)中读取stdX。我正在使用子流程模块调用launcher

# When calling the launcher script:
cmd = "launcher value1 value2"
p = subprocess.Popen(cmd, 
    stdout=subprocess.PIPE, 
    stderr=subprocess.STDOUT,
    shell=True)
# read p.stdout ...

这创建了2个新进程,1个用于launcher脚本(例如pid:10000),另一个用于runtime(例如pid:10001),运行htop {{1} }}显示类似于此的内容:

tree

在某些时候,PID ... Command 12345 ... python server.py 10000 ... |- /bin/sh -c ./launcher value1 value2 10001 ... |- runtime --option1 value1 --option2 value2 想要停止server流程(通过发送runtime

SIGTERM

问题是这只会导致# When trying to stop the runtime: os.kill(p.pid, signal.SIGTERM) # Have also tried with p.terminate(), same results. 进程(pid:10000)无效,导致launcher无限期执行。每当runtime请求SIGTERM必须接收此信号以停止并正常退出时,我想将runtime正确地传播到server,否则会产生数据损坏)

我尝试使用runtime来杀死整个进程组,但它也会杀死os.killpg(...)(显然)。

如何将SIGTERM信号正确传播到子子流程?

1 个答案:

答案 0 :(得分:0)

以这种方式使用流程组:

p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                    shell=True, preexec_fn=os.setpgrp)

os.killpg(os.getpgid(p.pid), signal.SIGTERM)