execute a command with timeout in python

2155 ワード


class Command(threading.Thread):
    def __init__(self, command, cwd=None, writeConsole=True, timeout=60):
        threading.Thread.__init__(self)
        self.command = command
        self.cwd = cwd
        self.writeConsole = writeConsole
        self.timeout = timeout


    def run(self):
        if self.cwd is not None:
            print '[' + ' '.join(self.command) + '] in ' + self.cwd
        else:
            print '[' + ' '.join(self.command) + ']'
        self.p = subprocess.Popen(self.command, stdout=subprocess.PIPE,
                                  stderr=subprocess.PIPE, cwd=self.cwd)

        self.stdout_lines = []
        for stdout_line in iter(self.p.stdout.readline, b''):
            if self.writeConsole:
                sys.stdout.write(stdout_line)
            self.stdout_lines.append(stdout_line)

        self.stderr_lines = []
        for stderr_line in iter(self.p.stderr.readline, b''):
            if self.writeConsole:
                sys.stderr.write(stderr_line)
            self.stderr_lines.append(stderr_line)

        self.result = self.p.poll()


    def exec_command(self):
        self.start()
        self.join(self.timeout)

        if self.is_alive():
            print 'executing [' + ' '.join(self.command) + '] timeout with timeout in seconds =>', self.timeout
            self.p.terminate()      #use self.p.kill() if process needs a kill -9
            self.join()
            sys.exit(1)
        return (self.result, self.stdout_lines, self.stderr_lines)


if __name__ == "__main__":
      result, outs, errs = Command(
        ["/bin/sleep", "3"], writeConsole=True, timeout=2).exec_command()
    Command(
        ["/bin/echo", "3"], writeConsole=True, timeout=2).exec_command()