做个程序,需要用到系统的cpu、内存、网络的使用情况。于是乎就自己写一个。
要读取cpu的使用情况,首先要了解/proc/stat文件的内容,下图是/proc/stat文件的一个例子:
cpu、cpu0、cpu1……每行数字的意思相同,从左到右分别表示user、nice、system、idle、iowait、irq、softirq。根据系统的不同,输出的列数也会不同,比如ubuntu 12.04会输出10列数据,centos 6.4会输出9列数据,后边几列的含义不太清楚,每个系统都是输出至少7列。没一列的具体含义如下:
user:用户态的cpu时间(不包含nice值为负的进程所占用的cpu时间)
nice:nice值为负的进程所占用的cpu时间
system:内核态所占用的cpu时间
idle:cpu空闲时间
iowait:等待IO的时间
irq:系统中的硬中断时间
softirq:系统中的软中断时间
以上各值的单位都是jiffies,jiffies是内核中的一个全局变量,用来记录自系统启动一来产生的节拍数,在这里把它当做单位时间就行。
intr行中包含的是自系统启动以来的终端信息,第一列表示中断的总此数,其后每个数对应某一类型的中断所发生的次数
ctxt行中包含了cpu切换上下文的次数
btime行中包含了系统运行的时间,以秒为单位
processes/total_forks行中包含了从系统启动开始所建立的任务个数
procs_running行中包含了目前正在运行的任务的个数
procs_blocked行中包含了目前被阻塞的任务的个数
由于计算cpu的利用率用不到太多的值,所以截图中并未包含/proc/stat文件的所有内容。
知道了/proc文件的内容之后就可以计算cpu的利用率了,具体方法是:先在t1时刻读取文件内容,获得此时cpu的运行情况,然后等待一段时间在t2时刻再次读取文件内容,获取cpu的运行情况,然后根据两个时刻的数据通过以下方式计算cpu的利用率:100 - (idle2 - idle1)*100/(total2 - total1),其中total = user + system + nice + idle + iowait + irq + softirq。python代码实现如下:
#-*- encoding: utf-8 -*- import paramiko import time def getSSHOutput(host,userName,password,port): sshClient = paramiko.SSHClient() sshClient.set_missing_host_key_policy(paramiko.AutoAddPolicy()) sshClient.connect(host,port,userName,password) command = r"cat /proc/stat" stdin,stdout,stderr = sshClient.exec_command(command) outs = stdout.readlines() sshClient.close() return outs def getCpuInfo(outs): for line in outs: line = line.lstrip() counters = line.split() if len(counters) < 5: continue if counters[0].startswith('cpu'): break total = 0 for i in range(1, len(counters)): total = total + long(counters[i]) idle = long(counters[4]) return {'total':total, 'idle':idle} def calcCpuUsage(counters1, counters2): idle = counters2['idle'] - counters1['idle'] total = counters2['total'] - counters1['total'] return 100 - (idle*100/total) if __name__ == '__main__': while True: SSHOutput = getSSHOutput("192.168.144.128","root","******",22) counters1 = getCpuInfo(SSHOutput) time.sleep(1) SSHOutput = getSSHOutput("192.168.144.128","root","******",22) counters2 = getCpuInfo(SSHOutput) print (calcCpuUsage(counters1, counters2))
计算内存的利用率需要读取的是/proc/meminfo文件,该文件的结构比较清晰。
需要知道的是内存的使用总量为used = total - free - buffers - cached,python代码实现如下:
#-*- encoding: utf-8 -*- import paramiko import time def getSSHOutput(host,userName,password,port): sshClient = paramiko.SSHClient() sshClient.set_missing_host_key_policy(paramiko.AutoAddPolicy()) sshClient.connect(host,port,userName,password) command = r"cat /proc/meminfo" stdin,stdout,stderr = sshClient.exec_command(command) outs = stdout.readlines() sshClient.close() return outs def getMemInfo(outs): res = {'total':0, 'free':0, 'buffers':0, 'cached':0} index = 0 for line in outs: if(index == 4): break line = line.lstrip() memItem = line.lower().split() if memItem[0] == 'memtotal:': res['total'] = long(memItem[1]) index = index + 1 continue elif memItem[0] == 'memfree:': res['memfree'] = long(memItem[1]) index = index + 1 continue elif memItem[0] == 'buffers:': res['buffers'] = long(memItem[1]) index = index + 1 continue elif memItem[0] == 'cached:': res['cached'] = long(memItem[1]) index = index + 1 continue return res def calcMemUsage(counters): used = counters['total'] - counters['free'] - counters['buffers'] - counters['cached'] total = counters['total'] return used*100/total if __name__ == '__main__': while True: SSHOutput = getSSHOutput("192.168.144.128","root","******",22) counters = getMemInfo(SSHOutput) time.sleep(1) print (calcMemUsage(counters))
三、获取网络的使用情况
获取网络使用情况需要读取的是/proc/net/dev文件,如下图所示,里边的内容也很清晰,不做过多的介绍,直接上python代码,取的是eth0的发送和收取的总字节数:
#-*- encoding: utf-8 -*- import paramiko import time def getSSHOutput(host,userName,password,port): sshClient = paramiko.SSHClient() sshClient.set_missing_host_key_policy(paramiko.AutoAddPolicy()) sshClient.connect(host,port,userName,password) command = r"cat /proc/net/dev" stdin,stdout,stderr = sshClient.exec_command(command) outs = stdout.readlines() sshClient.close() return outs def getNetInfo(dev,outs): res = {'total':0, 'in':0, 'out':0} for line in outs: if line.lstrip().startswith(dev): line = line.replace(':', ' ') items = line.split() res['in'] = long(items[1]) res['out'] = long(items[len(items)/2 + 1]) res['total'] = res['in'] + res['out'] return res if __name__ == '__main__': SSHOutput = getSSHOutput("192.168.144.128","root","******",22) print getNetInfo('eth0',SSHOutput)