-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmonitor-stack
More file actions
executable file
·114 lines (100 loc) · 2.88 KB
/
monitor-stack
File metadata and controls
executable file
·114 lines (100 loc) · 2.88 KB
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
#!/usr/bin/env python
#
# monitor a stack install job.
import re
import os
import sys
import time
from processes import parse_ps_output, ProcessTable, capture_output, process_cwd
from cpu_stats_linux import cpu_stats, idle_percent, diff_stats
def check_pid(pid):
""" Check For the existence of a unix pid. """
try:
os.kill(pid, 0)
except OSError:
return False
else:
return True
def pid_command_matches(ptable, pid):
cmd = ptable.command(pid)
os.path.basename(cmd)
def pids_for_progname(procs, progname):
"""Return a set of pids with a specific program name."""
found = set()
for p in procs:
cmd = p['COMMAND']
w = cmd.split(' ', 1)[0]
if os.path.basename(w) == progname:
found.add(p['PID'])
return found
def pids_for_stack_install(procs):
"""Return a set of pids for 'stack install' commands"""
found = set()
for p in procs:
cmd = p['COMMAND']
m = re.match('(\S*/)?stack install( |\Z)', cmd)
if m:
found.add(p['PID'])
return found
def collect_packages(ptable, pid, pkgs):
"""Collect the names of packages being processed by stack by looking
at the working directories of this process and all its descendants."""
cwd = process_cwd(pid) or ""
m = re.match('/tmp/stack\d+/([^/]+)', cwd)
if m:
pkgs.add(m.group(1))
for cpid in ptable.children(pid):
collect_packages(ptable, cpid, pkgs)
def die(msg):
sys.stderr.write(msg+"\n")
sys.exit(1)
def warn(msg):
sys.stderr.write(msg+"\n")
def determine_top_pid():
if len(sys.argv) > 1:
top_pid = sys.argv[1]
if re.match("\d+\Z", top_pid):
return top_pid # Note: return as a string, not an int
die("invalid top pid: " + top_pid)
while True:
ps_output = capture_output(["ps", "axo", "pid,ppid,command"])
procs = parse_ps_output(ps_output)
pids = pids_for_stack_install(procs)
if len(pids) > 1:
die("multiple stack install processes: " + ' '.join(pids))
elif len(pids) == 0:
warn("stack install not found -- sleeping")
time.sleep(3)
else:
top_pid = pids.pop()
return top_pid
def main():
# determine the pid of the top stack --install process
top_pid = determine_top_pid()
top_pid_int = int(top_pid)
print "monitoring pid", top_pid
sys.stdout.flush()
dead_count = 0
a = cpu_stats()
while True:
now = time.time()
time.sleep(1)
b = cpu_stats()
ps_output = capture_output(["ps", "axo", "pid,ppid,command"])
procs = parse_ps_output(ps_output)
ptable = ProcessTable(procs)
pkgs = set()
collect_packages(ptable, top_pid, pkgs)
diff = diff_stats(b,a)
print now, "{:.1f}".format(100*idle_percent(diff)), len(pkgs), ' '.join(pkgs)
sys.stdout.flush()
if not check_pid(top_pid_int):
dead_count += 1
if dead_count >= 3:
return
else:
dead_count = 0
time.sleep(5)
a = b
if __name__ == '__main__':
main()