如何使子进程运行60秒

时间:2014-12-12 12:15:48

标签: python linux subprocess

我有以下运行的python脚本。 我想运行子进程运行60秒然后将SIGINT信号发送到子进程并将输出写入file.If我使用sleep时子进程不运行。

#!/usr/bin/python
import os
import subprocess
PIPE = subprocess.PIPE
import signal
import time

def handler(signum, frame):
    pass

signal.signal(signal.SIGALRM, handler)
signal.alarm(60)
command = "strace -c ./server"
os.chdir("/root/Desktop/")
p = subprocess.Popen(command, stdout=PIPE, stderr=PIPE)
time.sleep(60)
p.send_signal(signal.SIGINT)
signal.alarm(0)
print p.communicate()[1]

2 个答案:

答案 0 :(得分:1)

在Python 3.3及更新版本中,有一个更简单的答案版本(未经测试的代码):

with open('output', 'wb', 0) as output_file:
    p = subprocess.Popen("strace -c ./server".split(),
                         stdout=output_file, stderr=subprocess.STDOUT, 
                         cwd="/root/Desktop/",
                         close_fds=True)
    try:
        p.wait(60) # Wait for the child process to finish, or for 60 seconds, which ever comes first.
    except subprocess.TimeoutExpired:
        p.send_signal(signal.SIGINT)
        p.wait() # Wait fro the process to actually exit after receiving the terminate signal.

另请参阅:https://docs.python.org/3/library/subprocess.html#subprocess.Popen.wait

答案 1 :(得分:0)

有几个问题:

  1. command应该是一个列表
  2. 您应该从p.stdout / p.stderr管道读取,否则如果子进程产生足够的输出,它可能会停止
  3. 你应该在这里使用 <{em> time.sleep()signal.alarm(),而不是两者。
  4.   

    我想运行子进程运行60秒,然后将SIGINT信号发送到子进程并将输出写入文件。

    启动子流程,将其输出重定向到文件:

    with open('output', 'wb', 0) as output_file:
        p = subprocess.Popen("strace -c ./server".split(),
                             stdout=output_file, stderr=subprocess.STDOUT, 
                             cwd="/root/Desktop/",
                             close_fds=True)
    

    在一分钟内发送SIGINT:

    class Alarm(Exception):
        pass
    
    def alarm_handler(signum, frame):
        raise Alarm
    
    # set signal handler
    signal.signal(signal.SIGALRM, alarm_handler)
    signal.alarm(60) # produce SIGALRM in a minute
    
    try:
        p.wait() # wait for the child process to finish
        signal.alarm(0) # cancel alarm
    except Alarm:
        p.send_signal(signal.SIGINT)
        p.wait()