Below is a simple Python module for remotely monitoring Windows machines. It is used to retrieve performance/health metrics.
I only implemented 5 functions:
- Uptime
- CPU Utilization
- Available Memory
- Memory Used
- Ping
To run this, you will first need to install the WMI module. Follow the instructions and get the download from here: http://timgolden.me.uk/python/wmi.html (hint: it is just a single script you can drop in the same directory your script runs from)
import re import wmi from subprocess import Popen, PIPE def get_uptime(computer, user, password): c = wmi.WMI(computer=computer, user=user, password=password, find_classes=False) secs_up = int([uptime.SystemUpTime for uptime in c.Win32_PerfFormattedData_PerfOS_System()][0]) hours_up = secs_up / 3600 return hours_up def get_cpu(computer, user, password): c = wmi.WMI(computer=computer, user=user, password=password, find_classes=False) utilizations = [cpu.LoadPercentage for cpu in c.Win32_Processor()] utilization = int(sum(utilizations) / len(utilizations)) # avg all cores/processors return utilization def get_mem_mbytes(computer, user, password): c = wmi.WMI(computer=computer, user=user, password=password, find_classes=False) available_mbytes = int([mem.AvailableMBytes for mem in c.Win32_PerfFormattedData_PerfOS_Memory()][0]) return available_mbytes def get_mem_pct(computer, user, password): c = wmi.WMI(computer=computer, user=user, password=password, find_classes=False) pct_in_use = int([mem.PercentCommittedBytesInUse for mem in c.Win32_PerfFormattedData_PerfOS_Memory()][0]) return pct_in_use def ping(host_name): p = Popen('ping -n 1 ' + host_name, stdout=PIPE) m = re.search('Average = (.*)ms', p.stdout.read()) if m: return True else: raise Exception
I am building some home-brewed monitoring tools that use these functions as a basis for plugins.
How are other people monitoring Windows from Python?
Suggestions?
Improvements?
14 comments:
Home grown? Ouch. Just install GroundWork Monitor. http://www.groundworkopensource.com/
ActivePython could be interpreted via WScript.exe with a .pys extension filename, which could invoke WMI without install pywin32 stuff, I guess
One of the things that we have to keep a close watch on is the amount of free disk space for all attached drives. You could add to and improve this:
import string
import wmi
class SysInfo(object):
def __init__(self, hostname=''):
if hostname == '':
self.host = 'localhost'
else:
self.host = hostname
try:
self.server = wmi.WMI(self.host)
except wmi.x_wmi:
print "%s is not available" % self.host
def GetLocalDrives(self):
driveList = []
for disk in self.server.Win32_LogicalDisk():
if disk.DriveType == 3:
driveList.append(str(disk.Name))
return driveList
def GetTotalDiskSpace(self, drive):
self.drive = drive
try:
for disk in self.server.Win32_LogicalDisk(Name=self.drive):
total = long(disk.Size) /1073741824.0
return total
except UnboundLocalError:
raise 'Drive Not Found'
def GetFreeDiskSpace(self, drive):
self.drive = drive
try:
for disk in self.server.Win32_LogicalDisk(Name=self.drive):
free = long(disk.FreeSpace) /1073741824.0
return total
except UnboundLocalError:
return 'Drive Not Found'
def GetUsedDiskSpace(self, drive):
self.drive = drive
total = self.GetTotalDiskSpace(self.drive)
free = self.GetFreeDiskSpace(self.drive)
used = (total - free)
return used
def GetPercentDiskUsage(self, drive):
self.drive = drive
total = self.GetTotalDiskSpace(self.drive)
used = self.GetUsedDiskSpace(self.drive)
per_used = (used * 100) / total
return per_used
def GetCpuList(self):
'''
Attempt to get a list containing the names of the CPUs in
the system. This should be one name per physical CPU but
it seems that hyperthreading seems to make it show 2x the
actual number.
'''
cpulist = []
cpudict = {}
for cpu in self.server.Win32_Processor():
name = string.strip(str(cpu.Name))
deviceid = str(cpu.DeviceID)
cpudict = {deviceid:name}
cpulist.append(cpudict)
return cpulist
def GetNumCpu(self):
'''
Call GetCpuList and then return the number of items in the list.
'''
cpus = self.GetCpuList()
return len(cpus)
def GetServiceStatus(self, caption):
self.caption = caption
for svc in self.server.Win32_Service(Caption=self.caption):
state = svc.State
return str(state)
def GetNodeName(self):
'''
This is for when you are looking at a clustered env and
want to know who the active node is.
'''
for os in self.server.Win32_OperatingSystem():
activeNode = os.CSName
return str(activeNode)
man that mangled the tabs. oh well you can get the idea.
> Home grown? Ouch.
> Just install GroundWork Monitor
I'm actually the author of the Web Plugin for GroundWork and Nagios, so I looked there first.
I'm building my own.. new wheel or not :)
@etank
thanks for the code.
If you have any more code for metrics, paste it in!
w00t, Doug Heffernan uses python too!
Why not use one of the windows clients for nagios http://nagios.sourceforge.net/docs/3_0/monitoring-windows.html ?
Then you can still call python scripts that are called on either the local machine or remotely using any Windows box as a WMI proxy.
@Anon,
I am not using Nagios. See my comment above.
Ah!
Excellent post! I have been trying to figure out how to use WMI to see if my Python app is taking up too much RAM.
I've been pulling out hair trying to figure out the syntax to get at the data in this class....
Thanks!
The wmi lib I believe only works via Windows right ? But there is a way to do it on Linux :-)
http://felimwhiteley.wordpress.com/2008/10/01/using-python-to-retrieve-wmi-data-using-wmic/
wmic is actually a library, I didn't realise it was Python initially.. oops. Uses Samba4 pre-release code to implement the WMI.
- FĂ©lim
Thanks for this post
Thanks Corey. I've been doing similar things with PHP and a mix of VBScript and SNMP, but want to go cross platform.
Don't suppose you'd like to share the multi-thread manager or point a Python beginner to somewhere? This is obviously key to getting some scale in any monitoring system.
http://www.wekadesign.co.nz/overview.html
Hey, nice tutorial. Thanks!
I wonder if the 'get_cpu' function could be used to check for remote server's crashes/BSOD/freezes/hangs?
How would one check that?
Post a Comment