【问题标题】:How to forcefully timeout a process that spawns subprocesses如何强制使产生子进程的进程超时
【发布时间】:2018-12-08 17:35:33
【问题描述】:

我需要运行可能会产生其他进程的进程(程序、bash 脚本等),但我还需要应用超时以防某些事情挂起,并且我希望程序在超时到期后继续执行。我正在使用以下 run() 函数:

import subprocess, shlex, threading
from threading import Timer

def run(cmd, timeout_sec=5):
    def kill_proc(proc, timedout):
        timedout['value'] = True
        proc.kill()

    try:
        proc = subprocess.Popen(shlex.split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE)

        timedout = {'value': False}
        timer = threading.Timer(timeout_sec, kill_proc, [proc, timedout])
        timer.start()
        stdout, stderr = proc.communicate()
        timer.cancel()

        return stdout.decode('utf-8'), stderr.decode('utf-8'), proc.returncode, timedout['value']
    except Exception as e:
        print('Could not execute: %s - with error: %s' % (cmd, e))
        return '', '', 1, False

在大多数情况下,它能够正常地超时调用,例如:

run(cmd='sleep 1m', timeout_sec=2)

它似乎挂断的地方是假设我有以下名为 sleeper.sh 的 bash 脚本:

#!/bin/bash
sleep 1m

如果我发出以下命令:

run(cmd='sleeper.sh', timeout_sec=2)

它将坐在那里等待 1 分钟,直到命令完成。有没有办法让我重写我的 run() 函数以强制使进程超时,而不管产生了什么子进程?

【问题讨论】:

    标签: python bash timeout subprocess popen


    【解决方案1】:

    这是关于如何在 bash 中实现此目的的示例代码。您也许可以将其应用到您的程序中:

    $ date; timeout 1 sleep 5 ; date
    Sat Dec  8 18:02:44 UTC 2018
    Sat Dec  8 18:02:45 UTC 2018
    

    简而言之,看看在命令开头添加“超时持续时间”是否有效。

    【讨论】:

    • 我看到它在 CentOS 上正常工作,但在 Mac OSX 上却不行。
    • 我删除了我以前的 cmets,因为它们不需要 - 我尝试了你的建议,即在我的命令前加上“timeout x”,它确实有效,但如果可能的话,我真的很喜欢, 来处理 Python 中的所有事情,因为它看起来有点笨拙。但是是的,它确实有效,而且我还可以从 timeout 命令中捕获错误级别 - 不幸的是,我无法从我尝试执行的程序中捕获错误级别。不是世界末日,但它仍然增加了我宁愿在 Python 中处理的另一层。我仍然会投票,因为它绝对是一个有创意且可用的解决方案!
    猜你喜欢
    • 2012-02-16
    • 2012-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-22
    • 2023-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多