<html>
  <head>
    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <div class="moz-cite-prefix">How to test this patch:<br>
      <br>
      1. run a command with long time.<b><br>
      </b><b>$ sudo python -c 'import sys;</b><b><br>
      </b><b>sys.path.insert(0, "src");</b><b><br>
      </b><b>from kimchi import utils;</b><b><br>
      </b><b>print utils.run_command([</b><b><font color="#3333ff">"dd",
          "if=/dev/zero", "of=/dev/null"]</font></b><b>, 1.5)'</b><br>
      <br>
      subprocess is killed by signal.SIGKILL for timeout 1.5 seconds<br>
      ('', '', -9, <font color="#ff0000">True</font>)<br>
      <br>
      2. run a command failed<br>
      <b>$ sudo python -c 'import sys;</b><b><br>
      </b><b>sys.path.insert(0, "src");</b><b><br>
      </b><b>from kimchi import utils;</b><b><br>
      </b><b>print utils.run_command(["<font color="#3333ff">not-command</font>"])'</b><br>
      <br>
      Failed to run command: not-command.<br>
        [Errno 2] No such file or directory<br>
      (None, None, None, False)<br>
      <br>
      <br>
      3. run a command with an error optional param<br>
      <b>$ sudo python -c 'import sys;</b><b><br>
      </b><b>sys.path.insert(0, "src");</b><b><br>
      </b><b>from kimchi import utils;</b><b><br>
      </b><b>print utils.run_command([<font color="#3333ff">"ls", "-w"</font>])'</b><br>
      <br>
      ('', "ls: option requires an argument -- 'w'\nTry 'ls --help' for
      more information.\n", 2, False)<br>
      <br>
      4. run a command successfully<br>
      <b>$ sudo python -c 'import sys;</b><b><br>
      </b><b>sys.path.insert(0, "src");</b><b><br>
      </b><b>from kimchi import utils;</b><b><br>
      </b><b>print utils.run_command([<font color="#3333ff">"echo",
          "test"</font>])'</b><br>
      <br>
      ('test\n', '', 0, False)<br>
      <br>
      <br>
      On 01/10/2014 10:10 PM, <a class="moz-txt-link-abbreviated" href="mailto:shaohef@linux.vnet.ibm.com">shaohef@linux.vnet.ibm.com</a> wrote:<br>
    </div>
    <blockquote
      cite="mid:1389363033-9334-2-git-send-email-shaohef@linux.vnet.ibm.com"
      type="cite">
      <pre wrap="">From: ShaoHe Feng <a class="moz-txt-link-rfc2396E" href="mailto:shaohef@linux.vnet.ibm.com">&lt;shaohef@linux.vnet.ibm.com&gt;</a>

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 <a class="moz-txt-link-rfc2396E" href="mailto:lvroyce@linux.vnet.ibm.com">&lt;lvroyce@linux.vnet.ibm.com&gt;</a>
Signed-off-by: ShaoHe Feng <a class="moz-txt-link-rfc2396E" href="mailto:shaohef@linux.vnet.ibm.com">&lt;shaohef@linux.vnet.ibm.com&gt;</a>
---
 src/kimchi/utils.py | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/src/kimchi/utils.py b/src/kimchi/utils.py
index af245c6..c7165ce 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,44 @@ 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()
+
+        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)
+
+        if proc.returncode == -9 and timeout_flag[0] is True:
+            kimchi_log.error("subprocess is killed by signal.SIGKILL "
+                             "for timeout %s seconds", timeout)
+
+        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()
</pre>
    </blockquote>
    <br>
    <br>
    <pre class="moz-signature" cols="72">-- 
Thanks and best regards!

Sheldon Feng(冯少合)<a class="moz-txt-link-rfc2396E" href="mailto:shaohef@linux.vnet.ibm.com">&lt;shaohef@linux.vnet.ibm.com&gt;</a>
IBM Linux Technology Center</pre>
  </body>
</html>