0

I have the following python script that runs. I want is to run the subprocess to run for 60 sec and then send the SIGINT signal to subprocess and write the output in file.If i use sleep the subprocess doesn't run.

#!/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]
user2591307
  • 119
  • 1
  • 2
  • 6
  • 1
    https://stackoverflow.com/questions/1191374/subprocess-with-timeout – behzad.nouri Dec 12 '14 at 12:20
  • related: [Stop reading process output in Python without hang?](http://stackoverflow.com/a/4418891/4279) – jfs Dec 12 '14 at 16:36
  • [related thread on python mailing list](https://mail.python.org/pipermail/python-list/2014-December/682746.html) – jfs Dec 13 '14 at 13:53

2 Answers2

1

In Python 3.3 and newer, there is a simpler version of the answer (untested code):

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.

See also: https://docs.python.org/3/library/subprocess.html#subprocess.Popen.wait

  • @user2591307: it won't work on Python 2.7 with stdlib's `subprocess` module but you could install [`subprocess32`](https://pypi.python.org/pypi/subprocess32/) package that should work on Linux. Note: `signal.alarm()` may be more efficient than [`p.wait(60)` that uses a busy-loop](https://hg.python.org/cpython/file/3a35638bce66/Lib/subprocess.py#l1539) -- though the difference is negligible. – jfs Dec 13 '14 at 12:22
  • @DragonFireCK: the question has no [tag:python-3.x] tag and the code in the question uses `print` statement i.e., the answer should show Python 2 solution – jfs Dec 13 '14 at 12:23
0

There are several issues:

  1. command should be a list
  2. you should read from p.stdout/p.stderr pipes otherwise the child process may stall if it generates enough output
  3. you should use either time.sleep() or signal.alarm() here, not both.

I want is to run the subprocess to run for 60 sec and then send the SIGINT signal to subprocess and write the output in file.

Start the subprocess, redirect its output to a file:

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)

Send SIGINT in a minute:

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()
jfs
  • 399,953
  • 195
  • 994
  • 1,670