This post introduces a Python class Command that can run a shell command with a time limit - the command will be killed after timer expires. This is implemented by threading and subprocess modules.

The Command class supports running command in two modes: run the command ignoring the output, or capture the output of the command through pipe.

The source code is also available in my GitHub.


import subprocess
import threading

""" Run system commands with timeout
"""
class Command(object):
    def __init__(self, cmd):
        self.cmd = cmd
        self.process = None
        self.out = None

    def run_command(self, capture = False):
        if not capture:
            self.process = subprocess.Popen(self.cmd,shell=True)
            self.process.communicate()
            return
        # capturing the outputs of shell commands
        self.process = subprocess.Popen(self.cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,stdin=subprocess.PIPE)
        out,err = self.process.communicate()
        if len(out) > 0:
            self.out = out.splitlines()
        else:
            self.out = None

    # set default timeout to 2 minutes
    def run(self, capture = False, timeout = 120):
        thread = threading.Thread(target=self.run_command, args=(capture,))
        thread.start()
        thread.join(timeout)
        if thread.is_alive():
            print 'Command timeout, kill it: ' + self.cmd
            self.process.terminate()
            thread.join()
        return self.out

'''basic test cases'''

# run shell command without capture
Command('pwd').run()
# capture the output of a command
date_time = Command('date').run(capture=True)
print date_time
# kill a command after timeout
Command('echo "sleep 10 seconds"; sleep 10; echo "done"').run(timeout=2)

The output of above test cases are:

$ python run_command_timed.py 
/Users/boyang/Documents/prog
['Fri Dec  2 09:17:50 PST 2016']
sleep 10 seconds
Command timeout, kill it: echo "sleep 10 seconds"; sleep 10; echo "done"

References: