-
Notifications
You must be signed in to change notification settings - Fork 1
/
ezshell.py
executable file
·97 lines (78 loc) · 2.47 KB
/
ezshell.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import subprocess
import threading
import os
import signal
# The utility is run in a fake environment, do no apply any operation that may
# change your system configuration
FAKE_EXEC = False
__version__ = "0.1.0"
def run(cmd, timeout=-1):
if 'FAKE_EXEC' in globals() and FAKE_EXEC:
print cmd, timeout
return None
else:
return EzShell(cmd, timeout)
class EzShell(object):
"""An easy way to execute shell commands.
Attributes:
cmd: Executing commands.
proc: A process object in executing.
timeout: Set timeout to stop the process.
-1 for don't wait the process stop,
0 for waiting process stop forever,
>0: timeout in seconds, force the process to stop
if process is still running
ret: Return data, including return value and output.
"""
def __init__(self, cmd, timeout=-1):
self.cmd = cmd
self.timeout = timeout
self.proc = None
self.ret = None
if self.timeout > 0:
self.countdown()
else:
self.run()
def run(self):
self.proc = subprocess.Popen(
self.cmd, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=True, preexec_fn=os.setsid)
if 0 <= self.timeout:
self.ret = self.proc.communicate()
def output(self):
if not self.ret:
self.ret = self.proc.communicate()
return self.ret[0].strip() if self.ret[0] else self.ret[0]
def err(self):
if not self.ret:
self.ret = self.proc.communicate()
return self.ret[1]
def returncode(self):
return self.proc.returncode
def terminate(self):
try:
self.proc.terminate()
os.killpg(self.proc.pid, signal.SIGKILL)
except OSError:
pass
def countdown(self):
try:
thread = threading.Thread(target=self.run)
thread.daemon = True
thread.start()
thread.join(self.timeout)
except:
self.terminate()
raise RuntimeError('Execute error: %s.' % self.cmd)
self.terminate()
if thread.is_alive():
raise RuntimeError('Execute timeout: %s.' % self.cmd)
if __name__ == '__main__':
cmd = 'ip a show | grep inet'
cmd = './sleep.sh'
ret = EzShell.run(cmd, 3)
print ret.output()
print ret.returncode()
print ret.err()