简体   繁体   English

超时子进程

[英]timeout a subprocess

I realize this might be a duplicate of Using module 'subprocess' with timeout . 我意识到这可能与使用带有超时的模块'subprocess'重复。 If it is, I apologize, just wanted to clarify something. 如果是的话,我道歉,只想澄清一些事情。

I'm creating a subprocess, which I want to run for a certain amount of time, and if it doesn't complete within that time, I want it to throw an error. 我正在创建一个子进程,我想运行一段时间,如果它在那段时间内没有完成,我希望它抛出一个错误。 Would something along the lines of the following code work or do we have to use a signal like answered in the other question? 以下代码中的某些内容是否有效,或者我们是否必须使用其他问题中回答的信号? Thanks in advance!: 提前致谢!:

def run(self):
    self.runTestCmd()
    self.waitTestComplete(self.timeout)

def runTestCmd(self):
    self.proc = subprocess.Popen("./configure", shell=True)

def waitTestComplete(self, timeout):
    st = time.time() 
    while (time.time()-st) < timeout:
        if self.proc.poll() == 0:
            return True
        else:
            time.sleep(2)
    raise TestError("timed out waiting for test to complete")

It would, but it has a problem. 它会,但它有一个问题。 The process will continue on doing whatever it is you asked it to do even after you've given up on it. 即使在你放弃之后,这个过程仍将继续做你要求它做的事情。 You'll have to send the process a signal to kill it once you've given up on it if you really want it to stop. 如果你真的希望它停止,你必须发送一个信号来杀死它。

Since you are spawning a new process ( ./configure which is presumably a configure script) that in turn creates a whole ton of sub-processes this is going to get a little more complex. 由于您正在生成一个新进程( ./configure ,可能是一个配置脚本),而这反过来会创建大量的子进程,这将变得更加复杂。

import os

def runTestCmd(self):
    self.proc = subprocess.Popen(["./configure"], shell=False,
                                 preexec_fn=os.setsid)

Then os.kill(-process.pid, signal.SIGKILL) should kill all the sub-processes. 然后os.kill(-process.pid, signal.SIGKILL)应该杀死所有子进程。 Basically what you are doing is using the preexec_fn to cause your new subprocess to acquire it's own session group . 基本上你正在做的是使用preexec_fn使你的新子preexec_fn 获得它自己的会话组 Then you are sending a signal to all processes in that session group. 然后,您将向该会话组中的所有进程发送信号。

Many processes that spawn subprocesses know that they need to clean up their subprocesses before they die. 产生子进程的许多进程都知道它们需要在它们死之前清理它们的子进程。 So it behooves you to try being nice to them if you can. 如果可以的话,你应该尝试对他们好。 Try os.signal(-process.pid, signal.SIGTERM) first, wait a second or two for the process to exit, then try SIGKILL . 首先尝试os.signal(-process.pid, signal.SIGTERM) ,等待一两秒钟让进程退出,然后尝试SIGKILL Something like this: 像这样的东西:

import time, os, errno, signal

def waitTestComplete(self, timeout):
    st = time.time() 
    while (time.time()-st) < timeout:
        if self.proc.poll() is not None:  # 0 just means successful exit
            # Only return True if process exited successfully,
            # otherwise return False.
            return self.proc.returncode == 0
        else:
            time.sleep(2)
    # The process may exit between the time we check and the
    # time we send the signal.
    try:
        os.kill(-self.proc.pid, signal.SIGTERM)
    except OSError, e:
        if e.errno != errno.ESRCH:
            # If it's not because the process no longer exists,
            # something weird is wrong.
            raise
    time.sleep(1)
    if self.proc.poll() is None: # Still hasn't exited.
        try:
            os.kill(-self.proc.pid, signal.SIGKILL)
        except OSError, e:
            if e.errno != errno.ESRCH:
                raise
    raise TestError("timed out waiting for test to complete")

As a side note, never, ever use shell=True unless you know for absolute certain that's what you want . 作为旁注, 永远不要使用shell=True除非你绝对确定这是你想要的 Seriously. 认真。 shell=True is downright dangerous and the source of many security issues and mysterious behavior. shell=True是彻头彻尾的危险,是许多安全问题和神秘行为的根源。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM