-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathproc.py
183 lines (169 loc) · 8.09 KB
/
proc.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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
import os
import sys
import re
import errno # Need this for comparing exception errors and seeing what type they are
import subprocess # For readOpenWindow()
from process import Process
from cpu import CPU
from userlist import UserList
class Proc:
def __init__(self):
self.proc = '/proc/'
self.processList = {} # Make a dictionary which is a hashtable
self.cpu = [] # cpu[0] should be the collective info on all CPUs
self.totalMem = 0
self.memStr = ""
self.userList = UserList()
self.openWindows = []
self.cpuStr = ""
# Will hold our pids that are inside /proc/ as well as the process's information
self.readData()
def readData(self):
self.userList = UserList() # Update our user list, never know if a new user is constructed
self.readTotalMem()
self.readcpuTimes()
self.readProcListData()
self.readOpenWindows()
# FIXME: skip looping and try to acess directly
def readTotalMem(self):
fd = open(self.proc + "/meminfo")
for i, line in enumerate(fd):
if i == 0:
# items = line.split(" ") # OLD
items = re.split("[\t ]+", line)
for j, item in enumerate(items):
if items[j].isdigit():
self.totalMem = int(items[j])
elif i == 1:
items = re.split("[\t ]+", line)
for j, item in enumerate(items):
if items[j].isdigit():
freeMem = int(items[j])
self.memStr = "{:.2f}".format((self.totalMem - freeMem)/(self.totalMem)*100)
else:
break
fd.close()
# FIXME: skip looping and try to acess directly
def readcpuTimes(self):
fd = open(self.proc + "/stat")
bufcpu = []
for i, line in enumerate(fd):
# What it looks like for the first line: cpu 67188 150 8766 5124308 14884 0 711 0 0 0
# Keep checking until cpu isn't the first word so we collected all times for CPUs
if re.match("^cpu",line) != None:
items = re.split("[\t ]+", line)
cpu = CPU(items[1],items[2],items[3],items[4],items[5],items[6],items[7],items[8])
bufcpu.append(cpu)
else:
break
fd.close()
# Get our interval from last scan
if len(self.cpu) != 0:
#changed the calculation to manually got the period, which is the differnce between everything added up last time and everything added this time.
#bufcpu[0].period = bufcpu[0].period - self.cpu[0].period
bufcpu[0].period = bufcpu[0].usertime + bufcpu[0].systime + bufcpu[0].idletime - self.cpu[0].usertime - self.cpu[0].systime - self.cpu[0].idletime
cpuPercent = ((bufcpu[0].usertime + bufcpu[0].systime - self.cpu[0].usertime - self.cpu[0].systime)/ bufcpu[0].period)*100
self.cpuStr = "{:.2f}".format(cpuPercent)
self.cpu = bufcpu
# Collect PIDs and statuses from each pid
def readProcListData(self):
bufprocessList = {}
debug = False # Incase we need to check our calculations
if debug:
print("-----------------------------------")
print(" Start of loop ")
print("-----------------------------------")
for pid in os.listdir(self.proc):
process = Process()
if not pid.isdigit():
continue
process.pid = pid
process.ramPercentage = 0
fd = open(self.proc + pid + "/status")
for i, line in enumerate(fd):
if debug:
print("({}) = {}, i={}".format(i+1,line,i))
if i == 7:
item = re.split("[\t ]+", line)
process.realUid = int(item[1])
fd.close()
if debug:
print("UID = {}".format(process.realUid))
fd = open(self.proc + pid + "/stat")
for i, line in enumerate(fd):
# item = line.split(" ") # OLD
item = re.split("[\t ]+", line)
if debug:
for x, iter in enumerate(item):
print("({}) = {}, x={}".format(x+1,iter,x))
process.name = item[1][1:-1]
process.state = item[2]
process.setFullState()
process.rss = item[23]
process.ramPercentage = int(process.rss)
process.ramPercentage = (process.ramPercentage*4096)/1024
process.ramPercentage = process.ramPercentage/self.totalMem
process.ramPercentage = process.ramPercentage*100
# Clamp 0 to 100
process.ramPercentage = max(0, min(process.ramPercentage, 100))
process.ramPercentage = "{:.2f}".format(process.ramPercentage)
process.utime = int(item[13])
process.stime = int(item[14])
if debug:
print("PID {} == {} item[0]".format(pid,item[0]))
print("RSS: {}".format(process.rss))
# Did the process exist already from last scan? Setup proper interval for calculation
lp = self.processList.get(pid)
if lp is None:
lastTimes = 0
else:
lastTimes = lp.utime + lp.stime
process.cpuPercentage = (process.utime + process.stime - lastTimes) / self.cpu[0].period * 100
# Clamp 0 to 100
process.cpuPercentage = max(0, min(process.cpuPercentage, 100))
process.cpuPercentage = "{:.2f}".format(process.cpuPercentage)
if debug:
print("PID: {}, {}% = ({} + {} - {}) / {} * 100".format(process.pid,process.cpuPercentage, process.utime, process.stime, lastTimes, self.cpu[0].period))
fd.close()
# Get the path of the program
try:
process.fullpath = os.readlink(self.proc + pid + "/exe") # We use os.system instead of os.readlink because of permission problems and the readlink command handles it ok
except PermissionError as err:
process.fullpath = "DENIED" # Permission was denied to read /exe
# Otherwise, something really bad happened
except:
print("Unexpected error:", sys.exc_info()[0])
raise
if process.fullpath != "DENIED":
# strip the process name off the full path
process.path = os.path.dirname(process.fullpath)
else:
process.path = "DENIED" # Permission was denied to read /exe
bufprocessList[pid] = process
self.processList = bufprocessList
if debug:
print("-----------------------------------")
print(" End of loop ")
print("-----------------------------------")
def readOpenWindows(self):
self.openWindows = []
ret = subprocess.run(['wmctrl', '-lp'],stdout=subprocess.PIPE,universal_newlines=True)
lines = re.split("(.+)\n", ret.stdout)
for line in lines:
# Split up the fields for each line
fields = re.match("(\w+)\s+(\w+)\s+(\w+)\s+(.[^\s]+)\s+(.+)", line)
if fields is not None:
pid = fields.group(3)
windowName = fields.group(5)
# Filter out ubuntu crap
if windowName == "Hud" or windowName == "unity-dash" or windowName == "unity-panel" or windowName == "unity-launcher" or windowName == "XdndCollectionWindowImp" or windowName == "Desktop":
continue
process = self.processList.get(pid)
if process is not None:
process.windowName = windowName
self.openWindows.append([pid, windowName, process.fullState])
# FIXME: Delete when done project
# For testing proc.py's data gathering
if __name__ == "__main__":
proc = Proc()
proc.readData()