python 结束进程 terminate_[python] subprocess.terminate()残留进程的处理方法

在一项针对不同远程点音视频流探测和统计任务中,系统使用ubuntu kylin通过contrab的方式定期探测分散的不同远程点传送回中心的音视频流过程中,发现系统在运行一段时间后就会残留的ffprobe进程越来越多,导致系统速度变慢卡死 ps -ef | grep ffprobe 查看了一下,系统中残留这大把没有返回的进程,对于没有返回的进程,我的处理方式是:

p = subprocess.Popen(probeUrl, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

t_begining = time.time()

seconds_passed = 0

while True:

# move on in case returning

if p.poll() is not None:

break

seconds_passed = time.time() - t_begining

# 如果30秒内没有返回就关闭进程

if  seconds_passed > 30:

p.terminate()

raise TimeoutError('ffprobe time out in 30 seconds')

time.sleep(0.1)

在实际使用过程中发现之所以有残留的原因是这样的,由于subprocess.Popen调用的是bash,probeUrl = “/home/jl/ffmpeg-2.8.5/ffprobe ‘”+ streamUrl +”‘”,系统首先启动了一个bash进程,再由bash进程启动ffprobe,从而生成了一个子进程,一共是两个进程,而p.terminate()只是结束了启动的bash,并没有将ffprobe进程结束,这样结束并抛出异常后,30秒内没有返回的ffprobe就挂死在系统中,一直处于等待返回的状态。每天都会有这样的进程产生,日积月累下来,系统自然出现问题。改进的方法是采用psutil包,逻辑是先关闭bash产生的所有ffprobe进行,然后再关闭bash。

def kill_child_processes(parent_pid, sig=signal.SIGKILL):

try:

p = psutil.Process(parent_pid)

except psutil.error.NoSuchProcess:

return

child_pid = p.get_children(recursive=True)

for pid in child_pid:

os.kill(pid.pid, sig)

# 如果30秒内没有返回就关闭进程

if  seconds_passed > 30:

kill_child_processes(p.pid)

p.terminate()

raise TimeoutError('ffprobe time out in 30 seconds')

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值