转载请注明出处:http://blog.csdn.net/dysj4099
前面的文章《利用Linux守护进程机制完成一个简单系统监控demo》中提到在Linux中如何利用Python读取procfs中的信息,并构建基于守护进程的系统运行状况监控程序。但目前云平台中Windows虚拟机的数量还是占大多数,虽然可以利用libvirt提供的API获取虚拟机的运行信息,不过对于Windows虚拟机来说,获取到的大部分系统信息都不准确,甚至是错误的。因此,一种解决方法是在Windows虚拟机中定制一个监控agent,通过agent实时获取系统信息并发布。
在Linux下,操作系统提供了procfs这样一种文件系统方便获取系统的各项运行信息。但Windows并没有提供类似procfs的机制,就必须另想办法了。好在微软提供了WMI(Windows Management Instrumentation)这样一种管理技术,它允许通过一个公共接口访问多种操作系统的构成单元,实现对操作系统的信息获取及管理操作。本文正是利用WMI进行数据获取。
要利用Python调用WMI获取信息,必须安装相关的软件包:
根据你的操作系统版本,下载相应版本安装。安装完后,就可以开始了:
CPU信息获取
我们首先以CPU为例,演示Python调用WMI的过程。在此我们调用了Win32_Processor这个类来获取cpu的信息,可以看到这个类的对象包含了与处理器相关的大部分有用信息,对于多核的处理器而言,将输出多个对象。其中LoadPercentage这个参数是指上一秒此处理器的工作负载,这就是我们需要的cpu_usage。
详细的Win32_Processor class说明,请参阅开发文档:
import wmi
import os
import sys
import platform
import time
import win32com.client as client
class DataPollster(object):
def get_cpu(self):
# Initilization
c = wmi.WMI()
data_dict = {}
for cpu in c.Win32_Processor():
device = cpu.DeviceID.lower()
# Get cpu_usage
data_dict[device] = {'volume':float(cpu.LoadPercentage), 'unit':'%'}
return data_dict
Memory信息获取
通过Win32_ComputerSystem可以获取机器内存总大小TotalPhysicalMemory,通过Win32_OperatingSystem获取可用内存大小,而Win32_PageFileUsage可以帮助我们获取虚拟内存及交换内存的相关信息。
def get_mem(self):
c = wmi.WMI ()
cs = c.Win32_ComputerSystem()
os = c.Win32_OperatingSystem()
pfu = c.Win32_PageFileUsage()
data_dict = {}
data_dict["MemTotal"] = {'volume':float(cs[0].TotalPhysicalMemory) / (1024*1024), 'unit':'MB'}
data_dict["MemFree"] = {'volume':float(os[0].FreePhysicalMemory)/1024, 'unit':'MB'}
data_dict["SwapTotal"] = {'volume':float(pfu[0].AllocatedBaseSize), 'unit':'MB'}
data_dict["SwapFree"] = {'volume':float(pfu[0].AllocatedBaseSize - pfu[0].CurrentUsage), 'unit':'MB'}
return {'data':data_dict, 'timestamp':time.asctime(time.localtime())}
跟CPU和mem类似,我们可以通过Win32_LogicalDisk获取磁盘信息,包括驱动器号、总容量、空闲容量、文件系统类型等。不同的是通过以下代码我们将看到磁盘实时I/O的获取方式。在这里我们通过Win32_PerfFormattedData_PerfDisk_LogicalDisk对象获取到逻辑磁盘的性能数,这个对象不能直接获取,必须通过WbemScripting.SWbemRefresher加入,并通过Refresh方法来刷新获取数据。这也适用于网络实时流量等数据的获取。
def get_disk(self):
c = wmi.WMI ()
data_dict = {}
data_dict['total_available'] = 0
data_dict['total_capacity'] = 0
data_dict['total_free'] = 0
# DriveType=3 : "Local Disk",
for disk in c.Win32_LogicalDisk (DriveType=3):
data_dict['total_available'] += round(float(disk.FreeSpace) / (1024*1024*1024), 2)
data_dict['total_capacity'] += round(float(disk.Size) / (1024*1024*1024), 2)
data_dict['total_free'] += round(float(disk.FreeSpace) / (1024*1024*1024), 2)
dev_tmp = {}
dev_tmp['dev'] = disk.DeviceID
dev_tmp['available'] = {'volume':round(float(disk.FreeSpace) / (1024*1024*1024), 2), 'unit':'GB'}
dev_tmp['capacity'] = {'volume':round(float(disk.Size) / (1024*1024*1024), 2), 'unit':'GB'}
dev_tmp['free'] = {'volume':round(float(disk.FreeSpace) / (1024*1024*1024), 2), 'unit':'GB'}
dev_tmp['fstype'] = disk.FileSystem
dev_tmp['mnt'] = ''
dev_tmp['used'] = round(long(disk.FreeSpace) / long(disk.Size), 2)
data_dict[disk.DeviceID] = dev_tmp
com = client.Dispatch("WbemScripting.SWbemRefresher")
obj = client.GetObject("winmgmts:\\root\cimv2")
diskitems = com.AddEnum(obj, "Win32_PerfFormattedData_PerfDisk_LogicalDisk").objectSet
com.Refresh()
for item in diskitems:
if item.Name in data_dict:
data_dict[item.Name]['io_stat'] = {}
data_dict[item.Name]['io_stat']['r/s'] = {'volume':float(item.DiskReadsPerSec), 'unit':''}
data_dict[item.Name]['io_stat']['w/s'] = {'volume':float(item.DiskWritesPerSec), 'unit':''}
data_dict[item.Name]['io_stat']['rkB/s'] = {'volume':(float(item.DiskReadBytesPerSec) / 1024), 'unit':'KB/s'}
data_dict[item.Name]['io_stat']['wkB/s'] = {'volume':(float(item.DiskWriteBytesPerSec) / 1024), 'unit':'KB/s'}
return {'data':data_dict, 'timestamp':time.asctime(time.localtime())}
照葫芦画瓢,Net可以通过以下方式获取:
def get_net(self):
c = wmi.WMI ()
com = client.Dispatch("WbemScripting.SWbemRefresher")
obj = client.GetObject("winmgmts:\\root\cimv2")
items = com.AddEnum(obj, "Win32_PerfRawData_Tcpip_NetworkInterface").objectSet
data_dict = {}
interfaces = []
for interface in c.Win32_NetworkAdapterConfiguration (IPEnabled=1):
print interface.IPAddress[0]
interfaces.append(interface.Description)
net_bytes_in = 0
net_bytes_out = 0
net_pkts_in = 0
net_pkts_out = 0
com.Refresh()
for item in items:
if item.Name in interfaces:
#print 'Name:%s -> B_in:%s, B_out:%s, P_in:%s, P_out:%s' %(item.Name, item.BytesReceivedPerSec, item.BytesSentPerSec, item.PacketsReceivedPerSec, item.PacketsSentPerSec)
net_bytes_in += long(item.BytesReceivedPerSec)
net_bytes_out += long(item.BytesSentPerSec)
net_pkts_in += long(item.PacketsReceivedPerSec)
net_pkts_out += long(item.PacketsSentPerSec)
time.sleep(1)
net_bytes_in_cur = 0
net_bytes_out_cur = 0
com.Refresh()
for item in items:
if item.Name in interfaces:
net_bytes_in = long(item.BytesReceivedPerSec) - net_bytes_in
net_bytes_in_cur += long(item.BytesReceivedPerSec)
net_bytes_out = long(item.BytesSentPerSec) - net_bytes_out
net_bytes_out_cur += long(item.BytesSentPerSec)
net_pkts_in = long(item.PacketsReceivedPerSec) - net_pkts_in
net_pkts_out = long(item.PacketsSentPerSec) - net_pkts_out
data_dict['net_bytes_in'] = {'volume':net_bytes_in, 'unit':'B/s'}
data_dict['net_bytes_in_sum'] = {'volume':net_bytes_in_cur, 'unit':'B'}
data_dict['net_bytes_out'] = {'volume':net_bytes_out, 'unit':'B/s'}
data_dict['net_bytes_out_sum'] = {'volume':net_bytes_out_cur, 'unit':'B'}
data_dict['net_pkts_in'] = {'volume':net_pkts_in, 'unit':'p/s'}
data_dict['net_pkts_out'] = {'volume':net_pkts_out, 'unit':'p/s'}
return {'data':data_dict, 'timestamp':time.asctime(time.localtime())}
小结:
本文通过几个例子说明如何使用Python通过WMI获取Windows系统信息。其中涉及到的Win32类定义请参阅微软官方开发文档。下篇将演示如何用Windows服务框架包装监控轮询任务。