python server agent_Python实现Windows监控agent(上)

转载请注明出处: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())}

Disk信息获取

跟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信息获取

照葫芦画瓢,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())}

需要注意的是,虽然在

Win32_PerfRawData_Tcpip_NetworkInterface

的文档中,

BytesReceivedPerSec

被解释为“Rate at which bytes are received on the interface, including framing characters.”,但是我仍然发现这类以

PerSec

结尾的参数都是累积值而不是真正的速率,因此我使用休眠1秒后取delta的方式求网卡的瞬时速率。

小结:

本文通过几个例子说明如何使用Python通过WMI获取Windows系统信息。其中涉及到的Win32类定义请参阅微软官方开发文档。下篇将演示如何用Windows服务框架包装监控轮询任务。 相关

代码下载

Github

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值