10月开始学习python, 学习一段时间之后,发现python真的是一门非常优美,开发迅速的语言, 漂亮的缩进, 功能强大的模块,丰富的图形库, 同时还能自己用c/c++添加你需要的扩展。
10月28号的, 在熟悉了这么一段时间后, 简单的用python+wxPython写了一个linux下的系统监控程序, 主要监控系统的cpu,内存,网络流量,磁盘, 主要是直接分析proc来获取各种信息。 然后图形界面是wxPython, 功能简单,直观。
如图(各种数据都是每秒钟刷新一次):
贴出监控的代码,图形界面的就不贴了,欢迎大家指点:
代码
import
threading,re,time,sys,os
from subprocess import *
from shlex import split
# global Variables
prev_cpu_info = { " user " :0, " system " :0, " idle " :0, " iowait " :0}
cpu_stat = []
prev_partition_info = []
HZ = 100
SLEEP_TIME = 3
prev_net_info = { " in " :0, " out " :0}
class SysMonitor(threading.Thread):
def __init__ (self,name,eventList,eventListMutex):
threading.Thread. __init__ (self)
self.name = name
self.eventList = eventList
self.eventListMutex = eventListMutex
self.running = True
self.runningMutex = threading.Lock()
def stop(self):
self.runningMutex.acquire()
self.running = False
self.runningMutex.release()
def calculate_deltams(self):
ncpu = self.get_numbers_of_cpu()
if len(cpu_stat) == 0:
raise Exception( " Please run check_cpu() at first! " )
deltams = 1000.0 * ((cpu_stat[ ' user ' ] + cpu_stat[ ' system ' ] + cpu_stat[ ' idle ' ] + cpu_stat[ ' iowait ' ]) - (prev_cpu_info[ ' user ' ] + prev_cpu_info[ ' system ' ] + prev_cpu_info[ ' idle ' ] + prev_cpu_info[ ' iowait ' ])) / ncpu / HZ
return deltams
def get_numbers_of_cpu(self):
try :
cpufp = file( " /proc/cpuinfo " )
ncpu = 0
while True:
line = cpufp.readline()
if len(line) < 1 :
break
if re.search(r " processor\t: " ,line) != None:
ncpu += 1
finally :
cpufp.close()
return ncpu
def get_cpu_stat(self):
cpu_info = {
" user " : 0,
" system " : 0,
" idle " : 0,
" iowait " : 0
}
try :
cpustatfp = file( " /proc/stat " )
line = split(cpustatfp.readline())
cpu_info[ ' user ' ] = float(line[ 1 ]) + float(line[ 2 ])
cpu_info[ ' system ' ] = float(line[ 3 ]) + float(line[ 6 ]) + float(line[ 7 ])
cpu_info[ ' idle ' ] = float(line[ 4 ])
cpu_info[ ' iowait ' ] = float(line[ 5 ])
finally :
cpustatfp.close()
return cpu_info
def check_cpu(self):
global prev_cpu_info,cpu_stat
cpu = {
" user " : 0,
" system " : 0,
" idle " : 0,
" iowait " : 0
}
if prev_cpu_info[ ' system ' ] == 0:
prev_cpu_info = self.get_cpu_stat()
time.sleep( 1 )
else :
prev_cpu_info = cpu_stat
cpu_stat = self.get_cpu_stat()
cpu[ ' user ' ] = cpu_stat[ ' user ' ] - prev_cpu_info[ ' user ' ]
cpu[ ' system ' ] = cpu_stat[ ' system ' ] - prev_cpu_info[ ' system ' ]
cpu[ ' idle ' ] = cpu_stat[ ' idle ' ] - prev_cpu_info[ ' idle ' ]
cpu[ ' iowait ' ] = cpu_stat[ ' iowait ' ] - prev_cpu_info[ ' iowait ' ]
total = (cpu[ ' user ' ] + cpu[ ' system ' ] + cpu[ ' idle ' ] + cpu[ ' iowait ' ] )
cpu[ ' user ' ] = cpu[ ' user ' ] / total * 100
cpu[ ' system ' ] = cpu[ ' system ' ] / total * 100
cpu[ ' idle ' ] = cpu[ ' idle ' ] / total * 100
cpu[ ' iowait ' ] = cpu[ ' iowait ' ] / total * 100
return cpu
def get_disk_stat(self):
diskfp = open( ' /proc/diskstats ' )
all_partition = []
curr = {
" major " :0,
" minor " :0,
" name " : None, # disk name
" rd_ios " : 0, # read I/O operation
" rd_merges " : 0, # readed merged
" rd_sectors " : 0, # sectors readed
" rd_ticks " : 0, # time in queue and server for read
" wr_ios " : 0, # write I/O operation
" wr_merges " : 0, # write merged
" wr_sectors " : 0, # sectors writed
" wr_ticks " : 0, # time in queue and server for write
" ticks " : 0, # time of request in queue
" aveq " : 0 # average queue length
}
while True:
line = split(diskfp.readline())
if len(line) == 0:
break
if int(line[ 3 ]) == 0:
continue
curr[ ' major ' ] = line[0]
curr[ ' minor ' ] = line[ 1 ]
curr[ ' name ' ] = line[ 2 ]
curr[ ' rd_ios ' ] = float(line[ 3 ])
curr[ ' rd_merges ' ] = float(line[ 4 ])
curr[ ' rd_sectors ' ] = float(line[ 5 ])
curr[ ' rd_ticks ' ] = float(line[ 6 ])
curr[ ' wr_ios ' ] = float(line[ 7 ])
curr[ ' wr_merges ' ] = float(line[ 8 ])
curr[ ' wr_sectors ' ] = float(line[ 9 ])
curr[ ' wr_ticks ' ] = float(line[ 10 ])
curr[ ' ticks ' ] = float(line[ 11 ])
curr[ ' aveq ' ] = float(line[ 12 ])
all_partition.append(curr.copy())
return all_partition
def check_disk(self):
global prev_partition_info
DISK_STAT = []
deltams = self.calculate_deltams()
curr_partition_info = self.get_disk_stat()
if len(prev_partition_info) == 0:
prev_partition_info = curr_partition_info
curr_partition_info = self.get_disk_stat()
partition_num = len(curr_partition_info)
i = 0
while i < partition_num:
disk_info = curr_partition_info[i]
prev_disk_info = prev_partition_info[i]
rd_ios = disk_info[ ' rd_ios ' ] - prev_disk_info[ ' rd_ios ' ]
rd_merges = disk_info[ ' rd_merges ' ] - prev_disk_info[ ' rd_merges ' ]
rd_sectors = disk_info[ ' rd_sectors ' ] - prev_disk_info[ ' rd_sectors ' ]
rd_ticks = disk_info[ ' rd_ticks ' ] - prev_disk_info[ ' rd_ticks ' ]
wr_ios = disk_info[ ' wr_ios ' ] - prev_disk_info[ ' wr_ios ' ]
wr_merges = disk_info[ ' wr_merges ' ] - prev_disk_info[ ' wr_merges ' ]
wr_sectors = disk_info[ ' wr_sectors ' ] - prev_disk_info[ ' wr_sectors ' ]
wr_ticks = disk_info[ ' wr_ticks ' ] - prev_disk_info[ ' wr_ticks ' ]
ticks = disk_info[ ' ticks ' ] - prev_disk_info[ ' ticks ' ]
aveq = disk_info[ ' aveq ' ] - prev_disk_info[ ' aveq ' ]
# prev_disk_info = disk_info #store the old info
prev_partition_info[i] = curr_partition_info[i]
i = i + 1
n_ios = rd_ios + wr_ios
n_ticks = rd_ticks + wr_ticks
n_kbytes = (rd_sectors + wr_sectors) / 2.0
queue = aveq / deltams
if n_ios:
size = n_kbytes / n_ios
wait = n_ticks / n_ios
else :
size = 0.0
wait = 0.0
busy = 100.0 * ticks / deltams
if busy > 100.0 :
busy = 100
# print rd_sectors,wr_sectors
readPerSec = str( 1000 * rd_sectors / deltams / 2.0 * 1024 )
writePerSec = str( 1000.0 * wr_sectors / deltams / 2.0 * 1024 )
readPerSec = readPerSec[:readPerSec.find( " . " ) + 3 ]
writePerSec = writePerSec[:writePerSec.find( " . " ) + 3 ]
# calculate total size and free size for every partition
try :
mounts = open( " /etc/mtab " )
# initialize
total_size = 0
free_size = 0
while True:
line = mounts.readline().strip()
if len(line) < 1 :
break
if line.find(disk_info[ ' name ' ] + " " ) != - 1 :
line = line.split()
s = os.statvfs(line[ 1 ])
total_size = s.f_bsize * s.f_blocks # unit : bytes
free_size = s.f_bsize * s.f_bavail #
break
finally :
mounts.close()
DISK_STAT.append({ " name " :disk_info[ " name " ], " total_size " :total_size, " free_size " :free_size, " readPerSec " :readPerSec, " writePerSec " :writePerSec, " wait " :wait, " queue " :queue, " size " :size})
return DISK_STAT
def get_net_stat(self,eth):
try :
netfp = file( " /proc/net/dev " )
while True:
line = netfp.readline()
if re.search(eth,line) != None:
line = split(line[ 7 :])
netin = int(line[0])
netout = int(line[ 8 ])
break
finally :
netfp.close()
return netin,netout
def checkNet(self):
global prev_net_info
NET_STATS = []
net_stat = self.get_net_stat( ' wlan0 ' ) # Caution!!! This should be the Ethernet card in use!!!
if prev_net_info[ ' in ' ] == 0 and prev_net_info[ ' out ' ] == 0:
prev_net_info[ ' in ' ] = net_stat[0]
prev_net_info[ ' out ' ] = net_stat[ 1 ]
NET_STATS.append((net_stat[0] - prev_net_info[ ' in ' ]) / SLEEP_TIME )
NET_STATS.append((net_stat[ 1 ] - prev_net_info[ ' out ' ]) / SLEEP_TIME )
prev_net_info[ ' in ' ] = net_stat[0]
prev_net_info[ ' out ' ] = net_stat[ 1 ]
return NET_STATS
def checkMem(self):
# the memory status file
MEM_FILE = " /proc/meminfo "
# default status
MEM_STATUS = {
" MemTotal " :0,
" MemFree " :0,
" Cached " :0,
" SwapCached " :0,
" Active " :0,
" Inactive " :0,
" Inact_dirty " :0,
" Inact_clean " :0,
" HighTotal " :0,
" LowTotal " :0,
" SwapTotal " :0,
" SwapFree " :0
}
try :
fd = file(MEM_FILE, " r " )
mem_info_list = fd.readlines()
PATTERN = re.compile(r " ^(\w+):\s*(\d+)\s*(\w+) " ) # e.g:MemTotal: 2061480 kB
for line in mem_info_list:
# DEBUG
res = PATTERN.match(line)
if res:
var_list = res.groups()
if MEM_STATUS.has_key(var_list[0]):
MEM_STATUS[var_list[0]] = var_list[ 1 ]
fd.seek(0)
finally :
fd.close()
return MEM_STATUS
def run(self):
while True:
self.runningMutex.acquire()
if not self.running:
self.runningMutex.release()
break
self.runningMutex.release()
cpuStatus = self.check_cpu()
diskStatus = self.check_disk()
netStatus = self.checkNet()
memStatus = self.checkMem()
# add those status to eventList
# print cpuStatus
# print memStatus
# print diskStatus
# print netStatus
self.eventListMutex.acquire()
while len(self.eventList) > 0:
del self.eventList[0]
self.eventList.append({ " cpu " :cpuStatus, " mem " :memStatus, " disk " :diskStatus, " net " :netStatus}) # Changed!!! trasform the dictionary to string!!!
self.eventListMutex.release()
# Just for test
time.sleep(SLEEP_TIME)
if __name__ == ' __main__ ' :
monitor = SysMonitor( ' SysMonitor ' ,[],threading.Lock())
monitor.start()
from subprocess import *
from shlex import split
# global Variables
prev_cpu_info = { " user " :0, " system " :0, " idle " :0, " iowait " :0}
cpu_stat = []
prev_partition_info = []
HZ = 100
SLEEP_TIME = 3
prev_net_info = { " in " :0, " out " :0}
class SysMonitor(threading.Thread):
def __init__ (self,name,eventList,eventListMutex):
threading.Thread. __init__ (self)
self.name = name
self.eventList = eventList
self.eventListMutex = eventListMutex
self.running = True
self.runningMutex = threading.Lock()
def stop(self):
self.runningMutex.acquire()
self.running = False
self.runningMutex.release()
def calculate_deltams(self):
ncpu = self.get_numbers_of_cpu()
if len(cpu_stat) == 0:
raise Exception( " Please run check_cpu() at first! " )
deltams = 1000.0 * ((cpu_stat[ ' user ' ] + cpu_stat[ ' system ' ] + cpu_stat[ ' idle ' ] + cpu_stat[ ' iowait ' ]) - (prev_cpu_info[ ' user ' ] + prev_cpu_info[ ' system ' ] + prev_cpu_info[ ' idle ' ] + prev_cpu_info[ ' iowait ' ])) / ncpu / HZ
return deltams
def get_numbers_of_cpu(self):
try :
cpufp = file( " /proc/cpuinfo " )
ncpu = 0
while True:
line = cpufp.readline()
if len(line) < 1 :
break
if re.search(r " processor\t: " ,line) != None:
ncpu += 1
finally :
cpufp.close()
return ncpu
def get_cpu_stat(self):
cpu_info = {
" user " : 0,
" system " : 0,
" idle " : 0,
" iowait " : 0
}
try :
cpustatfp = file( " /proc/stat " )
line = split(cpustatfp.readline())
cpu_info[ ' user ' ] = float(line[ 1 ]) + float(line[ 2 ])
cpu_info[ ' system ' ] = float(line[ 3 ]) + float(line[ 6 ]) + float(line[ 7 ])
cpu_info[ ' idle ' ] = float(line[ 4 ])
cpu_info[ ' iowait ' ] = float(line[ 5 ])
finally :
cpustatfp.close()
return cpu_info
def check_cpu(self):
global prev_cpu_info,cpu_stat
cpu = {
" user " : 0,
" system " : 0,
" idle " : 0,
" iowait " : 0
}
if prev_cpu_info[ ' system ' ] == 0:
prev_cpu_info = self.get_cpu_stat()
time.sleep( 1 )
else :
prev_cpu_info = cpu_stat
cpu_stat = self.get_cpu_stat()
cpu[ ' user ' ] = cpu_stat[ ' user ' ] - prev_cpu_info[ ' user ' ]
cpu[ ' system ' ] = cpu_stat[ ' system ' ] - prev_cpu_info[ ' system ' ]
cpu[ ' idle ' ] = cpu_stat[ ' idle ' ] - prev_cpu_info[ ' idle ' ]
cpu[ ' iowait ' ] = cpu_stat[ ' iowait ' ] - prev_cpu_info[ ' iowait ' ]
total = (cpu[ ' user ' ] + cpu[ ' system ' ] + cpu[ ' idle ' ] + cpu[ ' iowait ' ] )
cpu[ ' user ' ] = cpu[ ' user ' ] / total * 100
cpu[ ' system ' ] = cpu[ ' system ' ] / total * 100
cpu[ ' idle ' ] = cpu[ ' idle ' ] / total * 100
cpu[ ' iowait ' ] = cpu[ ' iowait ' ] / total * 100
return cpu
def get_disk_stat(self):
diskfp = open( ' /proc/diskstats ' )
all_partition = []
curr = {
" major " :0,
" minor " :0,
" name " : None, # disk name
" rd_ios " : 0, # read I/O operation
" rd_merges " : 0, # readed merged
" rd_sectors " : 0, # sectors readed
" rd_ticks " : 0, # time in queue and server for read
" wr_ios " : 0, # write I/O operation
" wr_merges " : 0, # write merged
" wr_sectors " : 0, # sectors writed
" wr_ticks " : 0, # time in queue and server for write
" ticks " : 0, # time of request in queue
" aveq " : 0 # average queue length
}
while True:
line = split(diskfp.readline())
if len(line) == 0:
break
if int(line[ 3 ]) == 0:
continue
curr[ ' major ' ] = line[0]
curr[ ' minor ' ] = line[ 1 ]
curr[ ' name ' ] = line[ 2 ]
curr[ ' rd_ios ' ] = float(line[ 3 ])
curr[ ' rd_merges ' ] = float(line[ 4 ])
curr[ ' rd_sectors ' ] = float(line[ 5 ])
curr[ ' rd_ticks ' ] = float(line[ 6 ])
curr[ ' wr_ios ' ] = float(line[ 7 ])
curr[ ' wr_merges ' ] = float(line[ 8 ])
curr[ ' wr_sectors ' ] = float(line[ 9 ])
curr[ ' wr_ticks ' ] = float(line[ 10 ])
curr[ ' ticks ' ] = float(line[ 11 ])
curr[ ' aveq ' ] = float(line[ 12 ])
all_partition.append(curr.copy())
return all_partition
def check_disk(self):
global prev_partition_info
DISK_STAT = []
deltams = self.calculate_deltams()
curr_partition_info = self.get_disk_stat()
if len(prev_partition_info) == 0:
prev_partition_info = curr_partition_info
curr_partition_info = self.get_disk_stat()
partition_num = len(curr_partition_info)
i = 0
while i < partition_num:
disk_info = curr_partition_info[i]
prev_disk_info = prev_partition_info[i]
rd_ios = disk_info[ ' rd_ios ' ] - prev_disk_info[ ' rd_ios ' ]
rd_merges = disk_info[ ' rd_merges ' ] - prev_disk_info[ ' rd_merges ' ]
rd_sectors = disk_info[ ' rd_sectors ' ] - prev_disk_info[ ' rd_sectors ' ]
rd_ticks = disk_info[ ' rd_ticks ' ] - prev_disk_info[ ' rd_ticks ' ]
wr_ios = disk_info[ ' wr_ios ' ] - prev_disk_info[ ' wr_ios ' ]
wr_merges = disk_info[ ' wr_merges ' ] - prev_disk_info[ ' wr_merges ' ]
wr_sectors = disk_info[ ' wr_sectors ' ] - prev_disk_info[ ' wr_sectors ' ]
wr_ticks = disk_info[ ' wr_ticks ' ] - prev_disk_info[ ' wr_ticks ' ]
ticks = disk_info[ ' ticks ' ] - prev_disk_info[ ' ticks ' ]
aveq = disk_info[ ' aveq ' ] - prev_disk_info[ ' aveq ' ]
# prev_disk_info = disk_info #store the old info
prev_partition_info[i] = curr_partition_info[i]
i = i + 1
n_ios = rd_ios + wr_ios
n_ticks = rd_ticks + wr_ticks
n_kbytes = (rd_sectors + wr_sectors) / 2.0
queue = aveq / deltams
if n_ios:
size = n_kbytes / n_ios
wait = n_ticks / n_ios
else :
size = 0.0
wait = 0.0
busy = 100.0 * ticks / deltams
if busy > 100.0 :
busy = 100
# print rd_sectors,wr_sectors
readPerSec = str( 1000 * rd_sectors / deltams / 2.0 * 1024 )
writePerSec = str( 1000.0 * wr_sectors / deltams / 2.0 * 1024 )
readPerSec = readPerSec[:readPerSec.find( " . " ) + 3 ]
writePerSec = writePerSec[:writePerSec.find( " . " ) + 3 ]
# calculate total size and free size for every partition
try :
mounts = open( " /etc/mtab " )
# initialize
total_size = 0
free_size = 0
while True:
line = mounts.readline().strip()
if len(line) < 1 :
break
if line.find(disk_info[ ' name ' ] + " " ) != - 1 :
line = line.split()
s = os.statvfs(line[ 1 ])
total_size = s.f_bsize * s.f_blocks # unit : bytes
free_size = s.f_bsize * s.f_bavail #
break
finally :
mounts.close()
DISK_STAT.append({ " name " :disk_info[ " name " ], " total_size " :total_size, " free_size " :free_size, " readPerSec " :readPerSec, " writePerSec " :writePerSec, " wait " :wait, " queue " :queue, " size " :size})
return DISK_STAT
def get_net_stat(self,eth):
try :
netfp = file( " /proc/net/dev " )
while True:
line = netfp.readline()
if re.search(eth,line) != None:
line = split(line[ 7 :])
netin = int(line[0])
netout = int(line[ 8 ])
break
finally :
netfp.close()
return netin,netout
def checkNet(self):
global prev_net_info
NET_STATS = []
net_stat = self.get_net_stat( ' wlan0 ' ) # Caution!!! This should be the Ethernet card in use!!!
if prev_net_info[ ' in ' ] == 0 and prev_net_info[ ' out ' ] == 0:
prev_net_info[ ' in ' ] = net_stat[0]
prev_net_info[ ' out ' ] = net_stat[ 1 ]
NET_STATS.append((net_stat[0] - prev_net_info[ ' in ' ]) / SLEEP_TIME )
NET_STATS.append((net_stat[ 1 ] - prev_net_info[ ' out ' ]) / SLEEP_TIME )
prev_net_info[ ' in ' ] = net_stat[0]
prev_net_info[ ' out ' ] = net_stat[ 1 ]
return NET_STATS
def checkMem(self):
# the memory status file
MEM_FILE = " /proc/meminfo "
# default status
MEM_STATUS = {
" MemTotal " :0,
" MemFree " :0,
" Cached " :0,
" SwapCached " :0,
" Active " :0,
" Inactive " :0,
" Inact_dirty " :0,
" Inact_clean " :0,
" HighTotal " :0,
" LowTotal " :0,
" SwapTotal " :0,
" SwapFree " :0
}
try :
fd = file(MEM_FILE, " r " )
mem_info_list = fd.readlines()
PATTERN = re.compile(r " ^(\w+):\s*(\d+)\s*(\w+) " ) # e.g:MemTotal: 2061480 kB
for line in mem_info_list:
# DEBUG
res = PATTERN.match(line)
if res:
var_list = res.groups()
if MEM_STATUS.has_key(var_list[0]):
MEM_STATUS[var_list[0]] = var_list[ 1 ]
fd.seek(0)
finally :
fd.close()
return MEM_STATUS
def run(self):
while True:
self.runningMutex.acquire()
if not self.running:
self.runningMutex.release()
break
self.runningMutex.release()
cpuStatus = self.check_cpu()
diskStatus = self.check_disk()
netStatus = self.checkNet()
memStatus = self.checkMem()
# add those status to eventList
# print cpuStatus
# print memStatus
# print diskStatus
# print netStatus
self.eventListMutex.acquire()
while len(self.eventList) > 0:
del self.eventList[0]
self.eventList.append({ " cpu " :cpuStatus, " mem " :memStatus, " disk " :diskStatus, " net " :netStatus}) # Changed!!! trasform the dictionary to string!!!
self.eventListMutex.release()
# Just for test
time.sleep(SLEEP_TIME)
if __name__ == ' __main__ ' :
monitor = SysMonitor( ' SysMonitor ' ,[],threading.Lock())
monitor.start()