-
Notifications
You must be signed in to change notification settings - Fork 0
/
procs.py
139 lines (106 loc) · 4.34 KB
/
procs.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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import os
import re
import signal
from subprocess import Popen, PIPE, STDOUT
import time
class BWProcess(object):
"""
Creates a wrapper around the subproces.Popen
@param command - The command to be run
@param options{} - Dictionary of options affecting how the command
is to be run
options.get_output - returns stdout from run() method
options.quiet - doesn't print the stdout from run() method
"""
def __init__(self, command, options=dict()):
self.command = command
def check_opt(key):
return options and key in options and options[key]
self._get_output = check_opt('get_output')
self._quiet = check_opt('quiet')
self.process = Popen(command, shell=True, stdout=PIPE,
stdin=PIPE, stderr=STDOUT)
def write(self, stdin):
# write <stdin> to the stdin stream of the process
self.process.stdin.write(stdin)
def passive_run(self):
# return stdout and stderr or process without calling .communicate()
stdout = self.process.stdout.readlines()
stderr = self.process.stderr.readlines()
return '\n'.join([stdout, stderr])
def run(self):
# run process and relinquish control of this thread to it until done.
stdout, stderr = self.process.communicate()
self.returncode = self.process.returncode
self.stdout = stdout
self.stderr = stderr
if not self._quiet:
print stdout
if self._get_output:
return stdout
def mk_process(command, options={'get_output': True, 'quiet': True}):
"""
Simple wrapper around BWProcess class, which simplifies calls for the
the most common use-case
@arg command - The command-line command to be run
@arg options - Pass-through to BWProcess options param
@return - The output of the run() method for the BWProcess
"""
return BWProcess(command, options).run()
def getUserFromUID(uid):
"""
Returns the username associated with the uid provided by a ps call.
@arg uid - The uid provided by a 'ps' call (int or str)
@return -(str) username associated with uid
"""
if uid.isdigit():
return mk_process('getent passwd "%s"' % uid).split(':')[0]
else:
return uid
def getOtherProcs(search_terms):
"""returns a list of process dictionaries for each non-self process matching
the given search terms
@param search_terms - regexp (or list of regexp) that must match the command
as reported in the ps %a field.
@return - [{uid, pid, name, command}] array of process dicts
"""
if isinstance(search_terms, str):
search_terms = [search_terms]
def mk_proc(ps_line):
"""return an info dict from the ps line"""
fields = ps_line.split()
print fields
return {
"uid": fields[0],
'pid': int(fields[1]),
'name': fields[2],
'command': ' '.join(fields[3:]),
}
def matches(proc):
"""determine if the proc item matches search_terms"""
return (proc['pid'] != os.getpid() and
all(re.search(term, proc['command']) for term in search_terms))
ps_output = mk_process('ps ahxw -o "%u %p %c %a"').strip().split('\n')
procs = [mk_proc(s) for s in ps_output]
return [p for p in procs if matches(p)]
def attemptToKillOtherProcs(search_terms, timeout=5):
"""
Attempts to kill all non-self processes that match the given search terms
Give up if the processes can't be killed after trying for a given length of time.
@param search_terms - regexp (or list of regexp) that must match the command
as reported in the ps %a field.
@param timeout - (int) number of seconds to wait before giving up
@return - (bool) did I successfully kill all requested processes?
"""
for proc in getOtherProcs(search_terms):
try:
os.kill(proc['pid'], signal.SIGTERM)
except:
pass
start = time.time()
while time.time() - start < timeout:
if len(getOtherProcs(search_terms)) > 0:
time.sleep(1)
else:
break
return len(getOtherProcs(search_terms)) == 0