How about just check timeout by
”proc.returncode == -9“, not sure we can kill the subprocess
manually.
The follow is an Example:
import subprocess
from threading import Timer
def run_command(cmd, timeout=None):
proc = None
timeout_flag = False
try:
proc = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
if timeout is not None:
timer = Timer(timeout, lambda proc:
proc.kill(), [proc])
timer.start()
out, error = proc.communicate()
print "Run command '%s'" % " ".join(cmd)
if out or error:
print "out:\n %s\nerror:\n %s" % (out, error)
if proc.returncode == -9:
timeout_flag = True
print "process is killed by signal.SIGKILL for
timeout %s seconds" % timeout
if timeout is not None:
timer.cancel()
return out, error, proc.returncode, timeout_flag
except Exception as e:
msg = "Failed to run command: %s." % " ".join(cmd)
print "%s\n %s" % (msg, e)
return None, None, None, timeout_flag
On 01/10/2014 04:16 PM, Royce Lv wrote:
On 2014年01月10日 09:00, shaohef@linux.vnet.ibm.com
wrote:
From: ShaoHe Feng
<shaohef@linux.vnet.ibm.com>
We need a common function to execute shell command.
We also need timeout when execute shell command.
A threading.Timer is used to send signal.SIGKILL to kill the
command
when timeout.
Signed-off-by: Royce Lv <lvroyce@linux.vnet.ibm.com>
Signed-off-by: ShaoHe Feng <shaohef@linux.vnet.ibm.com>
---
src/kimchi/utils.py | 39
+++++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/src/kimchi/utils.py b/src/kimchi/utils.py
index af245c6..94097ad 100644
--- a/src/kimchi/utils.py
+++ b/src/kimchi/utils.py
@@ -23,6 +23,7 @@
import cherrypy
import os
+import subprocess
import urllib2
@@ -30,6 +31,7 @@ from cherrypy.lib.reprconf import Parser
from kimchi import config
+from threading import Timer
kimchi_log = cherrypy.log.error_log
@@ -96,3 +98,40 @@ def check_url_path(path):
return False
return True
+
+
+def run_command(cmd, timeout=None):
+ def kill_proc(proc, timeout_flag):
+ timeout_flag[0] = True
+ proc.kill()
+
+ proc = None
+ timer = None
+ timeout_flag = [False]
+
+ try:
+ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ if timeout is not None:
+ timer = Timer(timeout, kill_proc, [proc,
timeout_flag])
+ timer.start()
I like the idea of using timer, I think the only thing we need to
take care is check timeout happens and report a specific error.
Or when we kill the proc and it is blocked, the proc.communicate()
error will not be 'timeout happens'
+
+ out, error = proc.communicate()
+ kimchi_log.debug("Run command '%s'", " ".join(cmd))
+
+ if out or error:
+ kimchi_log.debug("out:\n %s\nerror:\n %s", out,
error)
+
+ return out, error, proc.returncode, timeout_flag[0]
+ except Exception as e:
+ msg = "Failed to run command: %s." % " ".join(cmd)
+ msg = msg if proc is None else msg + "\n error code:
%s."
+ kimchi_log.error("%s\n %s", msg, e)
+
+ if proc:
+ return out, error, proc.returncode, timeout_flag[0]
+ else:
+ return None, None, None, timeout_flag[0]
+ finally:
+ if timer and not timeout_flag[0]:
+ timer.cancel()
--
Thanks and best regards!
Sheldon Feng(冯少合)<shaohef@linux.vnet.ibm.com>
IBM Linux Technology Center