Commit be553af7 by Peter Weidenbach

timeout option added

parent b76947be
from subprocess import Popen, PIPE, STDOUT
from subprocess import Popen, PIPE, STDOUT, TimeoutExpired
import logging
def execute_shell_command(shell_command):
def execute_shell_command(shell_command, timeout=None):
"""
Execute a shell command and return STDOUT and STDERR in one combined result string.
This function shall not raise any errors
......@@ -10,10 +11,10 @@ def execute_shell_command(shell_command):
:type shell_command: str
:return: str
"""
return execute_shell_command_get_return_code(shell_command)[0]
return execute_shell_command_get_return_code(shell_command, timeout=timeout)[0]
def execute_shell_command_get_return_code(shell_command):
def execute_shell_command_get_return_code(shell_command, timeout=None):
"""
Execute a shell command and return a tuple (program output, return code)
Program ouput includes STDOUT and STDERR.
......@@ -21,11 +22,20 @@ def execute_shell_command_get_return_code(shell_command):
:param shell_command: command to execute
:type shell_command: str
:param timeout: kill process after timeout seconds
:type: timeout: int
:return: str, int
"""
output = ""
rc = 1
with Popen(shell_command, shell=True, stdout=PIPE, stderr=STDOUT) as pl:
output = pl.communicate()[0].decode('utf-8', errors='replace')
pl = Popen(shell_command, shell=True, stdout=PIPE, stderr=STDOUT)
try:
output = pl.communicate(timeout=timeout)[0].decode('utf-8', errors='replace')
rc = pl.returncode
except TimeoutExpired:
logging.warning("Execution timeout!")
pl.kill()
output = pl.communicate()[0].decode('utf-8', errors='replace')
output += "\n\nERROR: execution timed out!"
rc = 1
return output, rc
import unittest
from time import time
from common_helper_process import execute_shell_command
from common_helper_process.fail_safe_subprocess import execute_shell_command_get_return_code
......@@ -23,3 +24,11 @@ class TestProcessHelper(unittest.TestCase):
output, rc = execute_shell_command_get_return_code("echo 'test 123' 1>&2 && exit 2")
self.assertEqual(output, 'test 123\n', 'result not correct')
self.assertEqual(rc, 2, 'return code not correct')
def test_execute_shell_command_time_out(self):
start_time = time()
output, rc = execute_shell_command_get_return_code("echo 'test 123' && for i in {1..10}; do sleep 1; done", timeout=1)
run_time = time() - start_time
self.assertEqual(output, 'test 123\n\n\nERROR: execution timed out!', 'timeout message not added')
self.assertEqual(rc, 1, 'return code not correct')
self.assertGreater(5, run_time, "command not aborted")
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment