python獲取linux系統內存、cpu、網絡使用情況
做個程序需要用到系統的cpu、內存、網絡的使用情況,百度之后發現目前使用python獲取這些信息大多是調用系統命令(top、free等)。其實多linux命令也是讀取/proc下的文件實現的,索性不如自己寫一個。
一、計算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代碼實現如下:
import time
def readCpuInfo():
f = open('/proc/stat')
lines = f.readlines();
f.close()
for line in lines:
line = line.lstrip()
counters = line.split()
if len(counters) < 5:
continue
if counters[0].startswith('cpu'):
break
total = 0
for i in xrange(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__':
counters1 = readCpuInfo()
time.sleep(0.1)
counters2 = readCpuInfo()
print calcCpuUsage(counters1, counters2):
二、計算內存的利用率
計算內存的利用率需要讀取的是/proc/meminfo文件,該文件的結構比較清晰,不需要額外的介紹,需要知道的是內存的使用總量為used = total - free - buffers - cached,python代碼實現如下:

def readMemInfo():
res = {'total':0, 'free':0, 'buffers':0, 'cached':0}
f = open('/proc/meminfo')
lines = f.readlines()
f.close()
i = 0
for line in lines:
if i == 4:
break
line = line.lstrip()
memItem = line.lower().split()
if memItem[0] == 'memtotal:':
res['total'] = long(memItem[1])
i = i +1
continue
elif memItem[0] == 'memfree:':
res['free'] = long(memItem[1])
i = i +1
continue
elif memItem[0] == 'buffers:':
res['buffers'] = long(memItem[1])
i = i +1
continue
elif memItem[0] == 'cached:':
res['cached'] = long(memItem[1])
i = i +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__':
counters = readMemInfo()
print calcMemUsage(counters)
三、獲取網絡的使用情況
獲取網絡使用情況需要讀取的是/proc/net/dev文件,如下圖所示,里邊的內容也很清晰,不做過的的介紹,直接上python代碼,取的是eth0的發送和收取的總字節數:

def readNetInfo(dev):
f = open('/proc/net/dev')
lines = f.readlines()
f.close()
res = {'in':0, 'out':0}
for line in lines:
if line.lstrip().startswith(dev):
# for centos
line = line.replace(':', ' ')
items = line.split()
res['in'] = long(items[1])
res['out'] = long(items[len(items)/2 + 1])
return res
if __name__ == '__main__':
print readNetInfo('eth0')
四、獲取網卡的ip地址和主機的cpu個數
這兩個函數是程序的其它地方需要用到,就順便寫下來:
import time
import socket
import fcntl
import struct
def getIpAddress(dev):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
a = s.fileno()
b = 0x8915
c = struct.pack('256s', dev[:15])
res = fcntl.ioctl(a, b, c)[20:24]
return socket.inet_ntoa(res)
def getCpuCount():
f = open('/proc/cpuinfo')
lines = f.readlines()
f.close()
res = 0
for line in lines:
line = line.lower().lstrip()
if line.startswith('processor'):
res = res + 1
return res
if __name__ == '__main__':
print getCpuCount()
print getIpAddress('eth0')
