我有一个python脚本,它启动了几个进程。每个进程基本上只调用一个shell脚本:
from multiprocessing import Process
import os
import logging
def thread_method(n = 4):
global logger
command = "~/Scripts/run.sh " + str(n) + " >> /var/log/mylog.log"
if (debug): logger.debug(command)
os.system(command)
我启动了几个这些线程,这些线程意味着在后台运行。我希望在这些线程上有一个超时,这样如果超过超时,它们就会被杀死:
t = []
for x in range(10):
try:
t.append(Process(target=thread_method, args=(x,) ) )
t[-1].start()
except Exception as e:
logger.error("Error: unable to start thread")
logger.error("Error message: " + str(e))
logger.info("Waiting up to 60 seconds to allow threads to finish")
t[0].join(60)
for n in range(len(t)):
if t[n].is_alive():
logger.info(str(n) + " is still alive after 60 seconds, forcibly terminating")
t[n].terminate()
问题是在进程线程上调用terminate()并没有杀死已启动的run.sh脚本 - 它继续在后台运行,直到我从命令行强制终止它,或者它在内部完成。有没有办法让终止也杀死os.system()创建的子shell?
答案 0 :(得分:4)
您应该使用事件来通知工作人员终止,使用subprocess
模块运行子进程,然后使用Popen.terminate()
终止它。调用Process.terminate()
将不允许其工作人员进行清理。请参阅the documentation for Process.terminate()
。
答案 1 :(得分:2)
请改为使用subprocess
,其对象明确具有terminate()
method。
答案 2 :(得分:2)
在Python 3.3中,子进程模块支持超时:http://docs.python.org/dev/library/subprocess.html
有关Python 2.x的其他解决方案,请查看此主题:Using module 'subprocess' with timeout
答案 3 :(得分:1)
基于Stop reading process output in Python without hang?:
import os
import time
from subprocess import Popen
def start_process(n, stdout):
# no need for `global logger` you don't assign to it
command = [os.path.expanduser("~/Scripts/run.sh"), str(n)]
logger.debug(command) # no need for if(debug); set logging level instead
return Popen(command, stdout=stdout) # run directly
# no need to use threads; Popen is asynchronous
with open('/tmp/scripts_output.txt') as file:
processes = [start_process(i, file) for i in range(10)]
# wait at most timeout seconds for the processes to complete
# you could use p.wait() and signal.alarm or threading.Timer instead
endtime = time.time() + timeout
while any(p.poll() is None for p in processes) and time.time() < endtime:
time.sleep(.04)
# terminate unfinished processes
for p in processes:
if p.poll() is None:
p.terminate()
p.wait() # blocks if `kill pid` is ignored
如果可用,请使用p.wait(timeout)
。