Link to home
Start Free TrialLog in
Avatar of ghelaniabhishek
ghelaniabhishek

asked on

Script to monitor CPU usage of 50+ servers

Hi All,

I am looking for a script that would monitor CPU usage, RAM usage and Disk space usage of approx 50+ servers.

I should be able to mention those servers in a seperate txt file and this script should pull the server name from this txt file.

should show the output in a HTML page something like...

                          CPU                 RAM               F Drive (Free space)
Computer 1         5%                    20%                80%
Computer 2         6%                    30%                60%
Computer 3         8%                    80%                50%
Computer 4         10%                  95%                0%

This values should refresh automatically in some interval and also, it should have some threshold, if breached it should show them in RED color. example, if CPU is more than 70% then it should show in red... same for others
Avatar of ghelaniabhishek
ghelaniabhishek

ASKER

can somebody please help??
Avatar of rejoinder
Here is a way you can pull this off using vbscript.  You will need the attached XML file plus script code.  In the XML file is where you can place your settings such as the polling interval, threshold numbers and server names.  As an added bonus I allow for you to group the servers for a nicer output.  You can group them anyway you want I suppose but in this example I grouped them by similar function.  Open the XML and you will see.
Polling CPU time for 50 servers is going to take a long, long time.  Believe me, this will be your biggest problem with using vbscript.  Since the script cannot thread like a normal program it hits each server one at a time.  The output does not display in real time because IE will not show the finished table until it gets the final </table> command.  The screen will remain white/blank for the duration it takes to reach all the servers.  The end result is what you asked for, just wait for it that's all.
on error resume next
Dim intInterval
Dim xmlDoc
Dim strQuery
Dim colIntervals, objInterval
Dim colGroups, objGroup
Dim colThresholds, colThreshold
Dim intCPU
Dim intRAM
Dim intHDD
Dim objIE
Dim txtTable
Dim objDocument

StartIE()
'Read XML file
Set xmlDoc = CreateObject("Microsoft.XMLDOM")
xmlDoc.async = false
xmlDoc.Load("servers.xml")
if xmlDoc.parseError.errorcode <> 0 then
	wscript.echo "Error opening file"
else
	Do While 1 <> 2
		objDocument.Writeln "<title>Server NOC</title>"
		objDocument.Writeln "<table width=100% border=""1"">"
		objDocument.Writeln "<tr bgcolor=""#7BA7E1""><th align=""left"">Server</th><th align=""left"">CPU</th><th align=""left"">RAM</th><th align=""left"">HDD</th></tr>"
		'Read XML file for changes since last poll
		Set xmlDoc = CreateObject("Microsoft.XMLDOM")
		xmlDoc.async = false
		xmlDoc.Load("servers.xml")
		
		'Get % values for INTERVAL, CPU, RAM and HDD
		intInterval = 300 'set a default value just in case
		intCPU = .9 'default value, red flag if over - ie CPU% > 90%
		intRAM = .8 'default value, red flag if over - ie RAM in use > 80%
		intHDD = .1 'default value, red flag if under - ie HDD free space < 10%
		
		strQuery = "/servers/ (interval | cpu | ram | hdd)"
		Set colThresholds = xmlDoc.selectNodes(strQuery)
		For Each objThreshold in colThresholds
			select case objThreshold.nodeName
				case "interval"
					intInterval = objThreshold.text
				case "cpu"
					intCPU = objThreshold.text
				case "ram"
					intRAM = objThreshold.text
				case "hdd"
					intHDD = objThreshold.text
			end select
		Next
		
		'Get group and server names from XML file
		strQuery = "/servers/group/ (name | server)"
		Set colGroups = xmlDoc.selectNodes(strQuery)
		For Each objGroup in colGroups
			'objGroup.nodeName = Either "name" or "server"
			'objGroup.text = Will either be the group name or the server name
			select case objGroup.nodeName
				Case "name"
					objDocument.Writeln "<tr bgcolor=""#CEDEF4""><td colspan=""4"">" & objGroup.text & "</td></tr>"
				Case "server"
					'wscript.echo objGroup.text
					objDocument.Writeln "<tr><td>" & objGroup.text & "</td>"
					set objSvc = GetObject("winmgmts:{impersonationLevel=impersonate}//" & objGroup.text & "/root/cimv2")
					if CINT(err.number) = 0 then
						'Check CPU usage
						strColour = ""
						strValue = ""
						objDocument.Writeln "<td>"
						set objRet = objSvc.InstancesOf("Win32_Processor")
						for each item in objRet
							strColour = "green"
							if item.LoadPercentage > intCPU then
								strColour = "red"
							end if
							strValue = item.LoadPercentage & "%"
							objDocument.Writeln "<font color=""" & strColour & """>" & strValue & "</font>&nbsp;"
						next
						objDocument.Writeln "</td>"
						
						strColour = ""
						strValue = ""
						set objRet = objSvc.InstancesOf("win32_OperatingSystem")
						for each item in objRet
							'Check RAM if over 80% in use red flag
							if ((item.TotalVisibleMemorySize-item.FreePhysicalMemory)/item.TotalVisibleMemorySize)*100 > intRAM*100 then
								strColour = "red"
							else
								strColour = "green"
							end if
							strValue = FormatNumber(((item.TotalVisibleMemorySize-item.FreePhysicalMemory)/item.TotalVisibleMemorySize)*100,0)& "%"
							objDocument.Writeln "<td><font color=""" & strColour & """>" & strValue & "</font></td>"
						next
						
						'Check hard drive space if free space is less than 10% red flag
						strColour = ""
						strValue = ""
						objDocument.Writeln "<td>"
						set objRet = objSvc.InstancesOf("win32_LogicalDisk")
						for each item in objRet
							if item.DriveType = 3 then
								'Default is drive has enough space and is green
								strColour = "Green"
								if (item.FreeSpace/item.size)*100 <= intHDD*100 then
									'There is less than a certain % of drive space left
									strColour = "Red"
								end if
								strValue = item.caption & " " & FormatNumber((item.FreeSpace/item.size)*100,0) & "%"
								objDocument.Writeln "<font color=""" & strColour & """>" & strValue & "</font>&nbsp;"
							end if
						next
						objDocument.Writeln "</td></tr>"
					else
						objDocument.Writeln "<td><font color=""red"">Server could not be reached</font></td></tr>"
					end if
					err.clear
			end select
		Next
		objDocument.Writeln "</table>"
		wscript.sleep intInterval*1000
		objDocument.body.innerHTML = ""
	loop
end if

Sub StartIE()
	Dim objWshShell
	Set objIE = CreateObject("InternetExplorer.Application")
	objIE.menubar = false
	objIE.toolbar = false
	objIE.statusbar = false
	objIE.addressbar = false
	objIE.resizable = true
	objIE.navigate ("about:blank")
	While (objIE.busy)
	wend
	set objDocument = objIE.document 
	objDocument.Open
	objIE.visible = True
End Sub

Open in new window

servers.xml
Thank you for the wonderful script. I tested it with 10 servers. And you were right, it took almost 55 Seconds to load it.

Do you recommend anything else that would give the output much quicker if not vbscript?
Also I played around a bit with the threshold limit. For HDD I set the limit to .2, ie if above 80% then it should be marked in red.
but in the output what I observed is that all the drives are listed in one colument,
example: C: 17%  D: 86%  F: 61%  
So, I expected that it would show D: 86% in red, but instead it showed C:17% in red and D and F in green
ASKER CERTIFIED SOLUTION
Avatar of rejoinder
rejoinder
Flag of Canada image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
About the HDD free space thing.  The calculation is getting the amout of free space remaining.  For example, C drive is 100MB and you are using 88MB, you have 12% free.  The HDD threshold being set to 10% sees this as OK and paints it green.  Now lets say you made the threshold .2 or 20%.  This would then get flagged in red showing 12% free.
So the number you are seeing is the amount of free space left on the drive; you are red flagging those drives that fall below a certain point of free space.

I did make a minor change to the code so there is only once place to enter the XML filename rather than two places as was the case above.
on error resume next
Dim intInterval
Dim xmlDoc
Dim strQuery
Dim colIntervals, objInterval
Dim colGroups, objGroup
Dim colThresholds, colThreshold
Dim intCPU
Dim intRAM
Dim intHDD
Dim objIE
Dim txtTable
Dim objDocument
Dim xmlFile

xmlFile = "servers.xml"

StartIE()
'Read XML file
Set xmlDoc = CreateObject("Microsoft.XMLDOM")
xmlDoc.async = false
xmlDoc.Load(xmlFile)
if xmlDoc.parseError.errorcode <> 0 then
	wscript.echo "Error opening file"
else
	Do While 1 <> 2
		objDocument.Writeln "<title>Server NOC</title>"
		objDocument.Writeln "<table width=100% border=""1"">"
		objDocument.Writeln "<tr bgcolor=""#7BA7E1""><th align=""left"">Server</th><th align=""left"">CPU</th><th align=""left"">RAM</th><th align=""left"">HDD</th></tr>"
		'Read XML file for changes since last poll
		Set xmlDoc = CreateObject("Microsoft.XMLDOM")
		xmlDoc.async = false
		xmlDoc.Load(xmlFile)
		
		'Get % values for INTERVAL, CPU, RAM and HDD
		intInterval = 300 'set a default value just in case
		intCPU = .9 'default value, red flag if over - ie CPU% > 90%
		intRAM = .8 'default value, red flag if over - ie RAM in use > 80%
		intHDD = .1 'default value, red flag if under - ie HDD free space < 10%
		
		strQuery = "/servers/ (interval | cpu | ram | hdd)"
		Set colThresholds = xmlDoc.selectNodes(strQuery)
		For Each objThreshold in colThresholds
			select case objThreshold.nodeName
				case "interval"
					intInterval = objThreshold.text
				case "cpu"
					intCPU = objThreshold.text
				case "ram"
					intRAM = objThreshold.text
				case "hdd"
					intHDD = objThreshold.text
			end select
		Next
		
		'Get group and server names from XML file
		strQuery = "/servers/group/ (name | server)"
		Set colGroups = xmlDoc.selectNodes(strQuery)
		For Each objGroup in colGroups
			'objGroup.nodeName = Either "name" or "server"
			'objGroup.text = Will either be the group name or the server name
			select case objGroup.nodeName
				Case "name"
					objDocument.Writeln "<tr bgcolor=""#CEDEF4""><td colspan=""4"">" & objGroup.text & "</td></tr>"
				Case "server"
					'wscript.echo objGroup.text
					objDocument.Writeln "<tr><td>" & objGroup.text & "</td>"
					set objSvc = GetObject("winmgmts:{impersonationLevel=impersonate}//" & objGroup.text & "/root/cimv2")
					if CINT(err.number) = 0 then
						'Check CPU usage
						strColour = ""
						strValue = ""
						objDocument.Writeln "<td>"
						set objRet = objSvc.InstancesOf("Win32_Processor")
						for each item in objRet
							strColour = "green"
							if item.LoadPercentage > intCPU then
								strColour = "red"
							end if
							strValue = item.LoadPercentage & "%"
							objDocument.Writeln "<font color=""" & strColour & """>" & strValue & "</font>&nbsp;"
						next
						objDocument.Writeln "</td>"
						
						strColour = ""
						strValue = ""
						set objRet = objSvc.InstancesOf("win32_OperatingSystem")
						for each item in objRet
							'Check RAM if over 80% in use red flag
							if ((item.TotalVisibleMemorySize-item.FreePhysicalMemory)/item.TotalVisibleMemorySize)*100 > intRAM*100 then
								strColour = "red"
							else
								strColour = "green"
							end if
							strValue = FormatNumber(((item.TotalVisibleMemorySize-item.FreePhysicalMemory)/item.TotalVisibleMemorySize)*100,0)& "%"
							objDocument.Writeln "<td><font color=""" & strColour & """>" & strValue & "</font></td>"
						next
						
						'Check hard drive space if free space is less than 10% red flag
						strColour = ""
						strValue = ""
						objDocument.Writeln "<td>"
						set objRet = objSvc.InstancesOf("win32_LogicalDisk")
						for each item in objRet
							if item.DriveType = 3 then
								'Default is drive has enough space and is green
								strColour = "Green"
								if (item.FreeSpace/item.size)*100 <= intHDD*100 then
									'There is less than a certain % of drive space left
									strColour = "Red"
								end if
								strValue = item.caption & " " & FormatNumber((item.FreeSpace/item.size)*100,0) & "%"
								objDocument.Writeln "<font color=""" & strColour & """>" & strValue & "</font>&nbsp;"
							end if
						next
						objDocument.Writeln "</td></tr>"
					else
						objDocument.Writeln "<td><font color=""red"">Server could not be reached</font></td></tr>"
					end if
					err.clear
			end select
		Next
		objDocument.Writeln "</table>"
		wscript.sleep intInterval*1000
		objDocument.body.innerHTML = ""
	loop
end if

Sub StartIE()
	Dim objWshShell
	Set objIE = CreateObject("InternetExplorer.Application")
	objIE.menubar = false
	objIE.toolbar = false
	objIE.statusbar = false
	objIE.addressbar = false
	objIE.resizable = true
	objIE.navigate ("about:blank")
	While (objIE.busy)
	wend
	set objDocument = objIE.document 
	objDocument.Open
	objIE.visible = True
End Sub

Open in new window

I liked your performance monitor option.
But is there a way were I can add counters for 50+ servers at once instead of manually adding counters for each server one by one. Its too time consuming
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
it gives "Error opening file" message
I fixed that issue. the file name was different. Checking the script now