最新消息:

linux下的系统监控程序(Python+wxPython)

cpuinfo admin 3549浏览 0评论

10月开始学习python, 学习一段时间之后,发现python真的是一门非常优美,开发迅速的语言,  漂亮的缩进, 功能强大的模块,丰富的图形库, 同时还能自己用c/c++添加你需要的扩展。

10月28号的, 在熟悉了这么一段时间后, 简单的用python+wxPython写了一个linux下的系统监控程序,  主要监控系统的cpu,内存,网络流量,磁盘, 主要是直接分析proc来获取各种信息。 然后图形界面是wxPython, 功能简单,直观。

如图(各种数据都是每秒钟刷新一次):

2010110222344043

2010110222350365

2010110222351446

 

2010110222381846

 

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()

相关资料:

转载请注明:爱开源 » linux下的系统监控程序(Python+wxPython)

您必须 登录 才能发表评论!