|
View previous topic :: View next topic |
Author |
Message |
greyhat64
Joined: 14 Mar 2008 Posts: 246 Location: USA
|
Posted: Thu Aug 14, 2008 12:45 am Post subject: Check all HD volumes for free space (variable threshold) |
|
|
I must first give credit to jivetolkein and his adaptation of Rob van der Woude's freespace.vbs for inspiring me to do this.
His original solution would parse all volumes on a remote server, and check that they don't fall below a critical value. That was great, but I needed the threshold to be a variable. One thing led to another, and I ended up with this:
This script includes:- The obligatory elements of the default AHM VBScript template (i.e. script response constants)
- Flexible argument parsing, type conversion/checking, error checking & syntax notification
- Flexible threshold checking - physical and percentage
- Percentage can be entered as a literal (15%% - you must double the % symbol) - or as a decimal (.15)
- Defaults for Computer ("." - local) and threshold (20%) if argument(s) not supplied
- Display of total freespace (in GB) AND percentage free.
Format (literal threshold provided =freespace(freepercent)
Format (percentage threshold provided =freepercent(freespace)
Code: | ' ===========HDFree.vbs===========
' Purpose: Query a local or remote computer's hard disk volumes for available disk space.
' The percentage of free space is compared against a user supplied critical threshold.
'
' Syntax: CSCRIPT HDFree.VBS {computer_name} {threshold}
' Where: {computer_name} =name of a WMI enabled computer (local or remote)
' Default ="." (local computer)
' {threshold} =minimum freespace
' If entered as an integer physical size is checked (in GB)
' If a decimal amount or an integer followed by "%%"
' percentage free is checked.
' Examples: HDFree.vbs Comp1 20 -->Checks all volumes on Comp1 for 20GB freespace
' HDFree.vbs Comp2 10%% -->Checks all volumes on Comp2 for 10% freespace
' HDFree.vbs Comp3 .15 -->Checks all volumes on Comp3 for 15% freespace
' Defaults: Local Computer (".") and 20%
'
' Output: [status]:{reply}
' [status] - Required. Format "scriptRes:{statusmsg}
' (see constants defined below)
' {reply} - Optional (on error this script always supplies one).
' May include simple description or system error codes
'
' NOTES: -This script has been modified to comply with (KS-Soft) Advanced Host Monitor's
' "shell script" method of monitoring.
' -Inspired by Glynn Seymours adaptation of Rob van der Woude's freespace.vbs
' http://www.robvanderwoude.com
' ==========Begin Script==========
Option Explicit
DIM sCompStatus, sType, sResult, sSyntaxDesc
DIM iThreshold
' *** Default Values & constants
iThreshold =.2
const statusAlive ="scriptRes:Host is alive:"
const statusDead ="scriptRes:No answer:"
const statusUnknown ="scriptRes:Unknown:"
const statusUnknownHost ="scriptRes:Unknown host:"
const statusOk ="scriptRes:Ok:"
const statusBad ="scriptRes:Bad:"
const statusBadContents ="scriptRes:Bad contents:"
const ShowSyntax ="/?"
' *** Parse the command-line arguments, check syntax, & perform necessary type conversions.
Select Case WScript.Arguments.Count
Case 0 ' *** No command line arguments
sCompStatus =ParseArg(".",0)
Case 1 ' *** Argument1 =computer name
sCompStatus =ParseArg(Wscript.Arguments(0),0)
Case 2 ' *** Argument2 =Critical threshold
sCompStatus =ParseArg(Wscript.Arguments(0),0)
iThreshold =ParseArg(Wscript.Arguments(1),1)
Case Else ' *** Maximum is 2 command line parameters - Show syntax
sCompStatus =ParseArg(ShowSyntax,99)
End Select
' *** If parsed arguments are 'bad' pass the results to StdOut
If InStr(sCompStatus,"scriptRes:") Then
WScript.StdOut.Write sCompStatus
ElseIf InStr(iThreshold,"scriptRes:") Then
WScript.StdOut.Write iThreshold
Else
' *** Otherwise call HDFreeTest Function & pass results to StdOut
WScript.StdOut.Write HDFreeTest(sCompStatus, iThreshold)
End if
' ===========End Script===========
'
' --------Functions & Subs--------
Function ParseArg(Arg, ArgNum)
' *** Purpose: Parse command-line arguments & display Syntax rules if necessary
DIM sReply, sSyntaxDesc
const Syntax ="Syntax: CSCRIPT HDFree.VBS {computer_name} {threshold}"
sSyntaxDesc = vbCrLf & "Where: {computer_name} =" & _
"name of a WMI enabled computer (local or remote)" & vbCrLf & _
vbTab & "{threshold} =minimum freespace" & vbCrLf & _
vbTab & vbTab & "An integer value is interpreted as physical size (in GB)" & vbCrLF & _
vbTab & vbTab & "A decimal value or an integer followed by '%%'" & vbCrLF & _
vbTab & vbTab & " is interpreted as a percentage" & vbCrLF & _
vbTab & vbTab & "Defaults: Computer: " & Chr(34) &"." & Chr(34) & _
" (local computer)" & vbCrLF & _
vbTab & vbTab & vbTab & " Threshold: 20%" & vbCrLF & _
"Inspired by Glynn Seymours adaptation of Rob van der Woude's freespace.vbs" & vbCrLf & _
vbTab & "http://www.robvanderwoude.com"
If InStr(Arg, "?") Then ArgNum =99
Select Case ArgNum
Case 0 ' *** sComputer Argument
ParseArg =CStr(Arg)
Case 1 ' *** iThreshold Argument
On Error Resume Next
If IsNumeric(Arg) Then
ParseArg =CSng(Arg)
Elseif InStrRev(Arg,"%")<>0 Then ParseArg =CSng(Trim(Left(Arg,InStrRev(Arg,"%")-1))/100)
Else
ParseArg =statusUnknown & "Syntax: Argument conversion error: " & Arg
On Error Goto 0
Exit Function
End If
If ParseArg <.01 or ParseArg >99 Then _
ParseArg=statusUnknown & "Threshold value out of bounds: " & Arg
On Error Goto 0
Case Else ' *** Display script syntax
ParseArg =statusUnknown & Syntax ' & sSyntaxDesc
' *** -------------------Remove this--^ if you wish to include Syntax Description
End Select
End Function
' --------------------------------
Function HDFreeTest(ArgComp, ArgThold)
' *** Purpose: Query Windows servers (WMI) for available Hard Disk free space
DIM sStatus, sReply
DIM iFree
DIM oWMIService, oItem, aItems
const GB=1073741824
On Error Resume Next
Set oWMIService =Getobject("winmgmts://" & ArgComp & "/root/cimv2")
If Err.Number Then
HDFreeTest =statusUnknownHost & "Server not found or not responding: Error # " & _
CStr(Err.Number) & " " & Err.Description
Exit Function
End If
Set aItems =oWMIService.ExecQuery("Select * from Win32_LogicalDisk where DriveType =3",,48)
If Err.Number Then
HDFreeTest =statusUnknown & "Error # " & CStr(Err.Number) & " " & Err.Description
Exit Function
End If
On Error GoTo 0
sStatus=statusOK
For Each oItem in aItems
If sReply<>"" Then sReply =sReply & ", "
'Calculate volume's percentage free space
iFree =Int(.5+(100 * oItem.FreeSpace / oItem.Size))
' *** If ANY volume falls below the critical threshold, set the AHM status to BAD
' *** then append this volumes free space and free space percentage to the return message
If iThreshold <1 Then
If iFree<iThreshold*100 Then sStatus =statusBad
sReply =sReply & oItem.Name & iFree & "%" & "(" & Round(oItem.FreeSpace / GB,2) & ")"
Else
If Round(oItem.Freespace / GB,2)<iThreshold Then sStatus ="statusBad"
sReply =sReply & oItem.Name & Round(oItem.FreeSpace / GB,2) & "(" &iFree & "%" & ")"
End If
Next
If sReply =Empty Then
HDFreeTest =statusUnknown & "Local Hard Disk(s) not found"
Else
HDFREETest =sStatus & sReply
End If
End Function |
Comments & suggestions are encouraged |
|
Back to top |
|
|
Paul_NHS
Joined: 25 Feb 2009 Posts: 59
|
Posted: Wed Feb 25, 2009 6:42 am Post subject: |
|
|
GreyHat64, I liked your script so much I thought we should have a more flexible version.
I have added the ability to supply drive specific sizes on the command line.
Usage: CSCRIPT HDFree.VBS {computer_name} {[drive:]threshold [[drive:]threshold] [.....]}
e.g. CSCRIPT HDFree.VBS Mycomp C:2 D:20%% 10%%
The final free space parameter sets the default for unspecified drives.
p.s. It is worth mentioning the mechanism for running this script.- Select the "Shell Script" test method.
- Click on the "Script Manager" icon.
- Select "New" for a new script.
- Name the script appropriately.
- Check the "Start Command" is set to: cmd /c cscript /B /E:VBScript %Script% %Params%
- Copy and paste the VBS file into the script box.
- Add a hint, e.g. {computer_name} {[drive:]threshold [[drive:]threshold] [.....]}
Now you can select the script from the HostMonitor dropdown and specify the parameters.
Note: You also don't require 2 percent signs in the parameters, one works nicely. e.g. Mycomp C:5% D:10% 20%
If you use this "Shell Script" method and you run a lot of these tests, check the potential problem discussed in the post where the code is shown below.
cheers, Paul
Code: | Please see lower down on this page for the latest code. |
Last edited by Paul_NHS on Wed Mar 11, 2009 8:04 am; edited 4 times in total |
|
Back to top |
|
|
greyhat64
Joined: 14 Mar 2008 Posts: 246 Location: USA
|
Posted: Wed Feb 25, 2009 8:49 am Post subject: |
|
|
Paul_HNS,
I just have one thing to say, NICE!!!
I was working on a similar modification, based on Kapz's request here.
Per his request v7.90 BETA now has a %AlertThresholdValue% variable that can be used for built-in tests like Drive Space, so I think I'm going to let it go.
Your thoughts. . .
I do have a couple of other mods I was working on, mostly to clean up the code. I may even 'trim the fat' and get rid of the verbose syntax description - useful if your running it from the command line, not any help for AHM shell script.
I'll use your new 'base' and post it soon. |
|
Back to top |
|
|
Paul_NHS
Joined: 25 Feb 2009 Posts: 59
|
Posted: Thu Feb 26, 2009 3:35 am Post subject: |
|
|
I agree, this does most of the things Kapz wants, although I was thinking the response could be tailored to make it easier to use in calculations. The trouble with a tailored response is what information do you return? It is essential to provide the drive name and the size/%, but this means you can't calculate %lastreply% - %reply%.
cheers, Paul |
|
Back to top |
|
|
greyhat64
Joined: 14 Mar 2008 Posts: 246 Location: USA
|
Posted: Thu Feb 26, 2009 12:25 pm Post subject: |
|
|
Your observation/question is exactly in line with mine, but I believe it's addressable. First, to summarize what we have to date:- If no arguments: Process all volumes on local computer with the '.2' default threshold. DONE
- If computer name supplied: Process all volumes on specified computer with the '.2' default threshold. DONE
- If a computer and threshold are supplied: Process all volumes on specified computer with the supplied threshold. DONE
- If a computer and a string of volume:thresholds are supplied along with a supplied other threshold: Process all specified volume:thresholds pairs on the specified computer and process all other voumes with the supplied other threshold. DONE
In order to address Kapz's needs:- If a computer and one volume is supplied (no supplied other threshold): Process specified volume on specified computer with the default threshold. {Reply=status:rawfreespace}
- If a computer and one volume:threshold is supplied (no supplied other threshold): Process only the specified volume on the specified computer with the specified threshold. {Reply=status:rawfreespace}
- Only the raw value is returned as a reply. That can be used in "Use Warning Status" processing or optional Alert Profile expressions.
- It's then up to the user to include the additional relavent info in their Test Name or Description fields for sorting purposes.
- If the user wants to process multiple volumes on the same computer this way then define multiple tests.
- The question at this point is, what does this script do that v7.90 Beta's[Drive Space] test doesn't do? Fixed & percentage thresholds. But you're still working with rawfreespace for optional processing, so is there value in this? Maybe we leave this to AHM Additionally, and a possible value add:- If a computer and a string of volume:thresholds are supplied (no supplied other threshold): Process only the specified volume:thresholds. {Standard reply}
- For instance, C: and D: are my critical volumes. Maybe I don't care about E: Also, for ease of parsing it might make sense for the second argument to be the optionally supplied 'other threshold'. Then all subsequent arguments are volume:[threshold].
- (If ':' in Arg2 then begin processing volume:threshold pairs.)
Your thoughts. . .
xxxxxI'm busy with some other internal projects right now, but will work on this as time permits. Ya wanta race!
xxxxx(You can opt to email me using the supplied link if you want to continue this offline) |
|
Back to top |
|
|
Paul_NHS
Joined: 25 Feb 2009 Posts: 59
|
Posted: Fri Feb 27, 2009 3:08 am Post subject: |
|
|
Quote: | If a computer and a string of volume:thresholds are supplied along with a supplied other threshold: Process all specified volume:thresholds pairs on the specified computer and process all other voumes with the supplied other threshold. DONE | I wanted it to behave as it did originally, except to modify the behaviour where a specific drive/threshold is supplied. Where a drive/threshold is not supplied, the default test is used.
Quote: | In order to address Kapz's needs:
If a computer and one volume is supplied (no supplied other threshold): Process specified volume on specified computer with the default threshold. {Reply=status:rawfreespace} | This can be dealt with using an additional modifier (/x) to tell the test to eXclusively test only the supplied drive. Using this modifier would cause the test to return only the value (% or GB) to allow testing with %status%.
Quote: | Also, for ease of parsing it might make sense for the second argument to be the optionally supplied 'other threshold'. Then all subsequent arguments are volume:[threshold].
- (If ':' in Arg2 then begin processing volume:threshold pairs.) | This is how it tests for drive:threshold parameters. It seemed the most sensible test as any other supplied value is either free space threshold for all drives, or an error.
Quote: | Ya wanta race! | Too easy! I'm happy to make these changes once we agree on them.
cheers, Paul |
|
Back to top |
|
|
greyhat64
Joined: 14 Mar 2008 Posts: 246 Location: USA
|
Posted: Fri Feb 27, 2009 3:57 am Post subject: |
|
|
Paul,
It's not in my nature, but I'll try to be brief.
First, I'll state again, you did a great job with your initial modifications. What you did was introduce the volume as a discreet argument.
In my mind, contextually, once you begin providing volumes or volume:threshold pairs your are moving away from the original 'process all volumes' model. But what you did was provide a way around that by providing an additional 'other' threshold.
Why not use that as the trigger. If the 'other' threshold is undefined then ignore nonspecified volumes. At that point no additional parameters (/x) are necessary. If the 'other' threshold is '.2' then we've simply matched the default.
But I'm so impressed with what you've done so far, you can put it together the way you see fit. Go for it!
-Joel |
|
Back to top |
|
|
Paul_NHS
Joined: 25 Feb 2009 Posts: 59
|
Posted: Fri Feb 27, 2009 4:21 am Post subject: |
|
|
Joel,
I like your idea but I see a potential problem. If you add an additional drive to a server but don't modify the test, the test would ignore the new drive. I would rather have "test everything" as the default and add exceptions, than forget to add drives and lose information.
I will go with my "/x" idea, which I feel is more in keeping with the "add exceptions" nature of the test.
cheers, Paul |
|
Back to top |
|
|
greyhat64
Joined: 14 Mar 2008 Posts: 246 Location: USA
|
Posted: Fri Feb 27, 2009 10:30 am Post subject: |
|
|
Paul,
You make a good point and I'll make a final plea for my case, but I think we have two very different perspectives. - You say include an additional '/x' parameter if you want to exclusively measure volume(s).
- I say that once you have specified volumes or, especially, volume:threshold pairs the inclusion or ommission of the 'other' threshold should dictate what happens to all other volumes.
- The user has already thought this through. The intentional specification of volume or volume:threshold pairs and the
omission of the 'other' threshold implies that they don't care about volumes other than those specified - even newly added ones.
- So why have the '/x' argument when the presense or absense of the 'other' threshold can accomplish the same thing?
- What I could see is an additional '/r' parameter to specify 'raw' freespace as a reply.
- Only available if one volume specified, ignored otherwise.
- Multiple volumes could be allowed, returning only the value of the first failed volume, and a blank or "OK" value otherwise. What 'dya think?
- To your point regarding loosing information, nothing says a user couldn't have a 'general' test measuring all volumes for a default or user specified threshold and additional tests measuring targeted volumes at different parameters. You might even set the additional tests as dependants of the first, only running if the first threshold has been crossed.
- I'm not really going to go this far, but having seen your current modifications you could make the case that a specified 'default' threshold should be a required argument and eliminate the 'hard coded' threshold of ".2".
- I've never been a fan of hard coded values other than constants, but I included localcomputer (".") and defaulttheshold (".2") in the original so the 'noob' could just plug in the script and get results.
Post your new code when you get a chance. I can't wait to see it.
BTW - Are you a member at Tek-Tips? A great forum site for everything IT, including some good VBScript/PowerShell code - highly recommended. |
|
Back to top |
|
|
Paul_NHS
Joined: 25 Feb 2009 Posts: 59
|
Posted: Fri Feb 27, 2009 11:03 am Post subject: |
|
|
Joel,
You have won me over to your view - ours are essentially the same, once you add test parameters you are changing the nature of the test, therefore the response should change.
Given that this test will be "tested" once the parameters have been changed, it will be obvious if the change does not produce the desired result.
I don't fancy a raw switch, this is automatically determined by the paramters anyway.
I will leave the default settings as a starting point for newbies.
cheers, Paul |
|
Back to top |
|
|
greyhat64
Joined: 14 Mar 2008 Posts: 246 Location: USA
|
Posted: Fri Feb 27, 2009 11:49 am Post subject: |
|
|
I can't wait to see it!
Suggestion: I was going to change this part of the code (from the original): Code: | ' *** If parsed arguments are 'bad' pass the results to StdOut
If InStr(sCompStatus,"scriptRes:") Then
WScript.StdOut.Write sCompStatus
ElseIf InStr(iThreshold,"scriptRes:") Then
WScript.StdOut.Write iThreshold
Else
' *** Otherwise call HDFreeTest Function & pass results to StdOut
WScript.StdOut.Write HDFreeTest(sCompStatus, aThreshold)
End if | Eliminating the If statement here, leaving the WScript.StdOut.Write HDFreeTest(sCompStatus, aThreshold) statement to stand alone.
Then insert into the ParseArg function, just above the 'End Function' statement, the following: Code: | ' *** If parsed argument is 'bad' pass the results to StdOut and Quit
If InStr(ParseArg,"scriptRes:") Then
WScript.StdOut.Write ParseArg
WScript.Quit
End If | I know it's a Quit inside a called Function (sometimes frowned upon), but it's a bit 'cleaner' I think. One test, no ElseIf's, and it exits with the first problem argument. |
|
Back to top |
|
|
Paul_NHS
Joined: 25 Feb 2009 Posts: 59
|
Posted: Mon Mar 02, 2009 3:51 am Post subject: |
|
|
Here is the definitive version - until we think of more things to add The test will only be performed on specified drives unless a default threshold is supplied.
I have also added extra syntax checking - found a bug which made me look a bit closer.
One thing I found in use on our system was that the script will time out if you fire a whole lot off at once - the "shell script" method is synchronous and can't handle more than about 5 tests at once. The solution is to place the disk space tests in a common folder and set "non-simultaneous test execution" under Special in the folder properties.
[Edit] Latest code as of 15:25, 3/3/2009 - Saves reams of code
[Edit] Latest code as of 09:56, 4/3/2009
[Edit] Latest code as of 10:13, 8/3/2009
[Edit] Latest code as of 10:13, 8/3/2009 - forgot to quote single replies, test type 3.
[Edit] Latest code as of 10:13, 19/10/2010 - Major change to accomodate drive mount points.
[Edit] Latest code as of 20/10/2010 - Fixed volume names returned as \\?\ (Win7 boot volumes), line 210.
Code: | ' ===========HDFree.vbs===========
' Purpose: Query a local or remote computer's hard disk volumes for available disk space.
' The percentage of free space is compared against a user supplied critical threshold.
'
' Syntax: CSCRIPT HDFree.VBS {computer_name} {[drive:]threshold [[drive:]threshold...]}
' Where: {computer_name} =name of a WMI enabled computer (local or remote)
' Default ="." (local computer)
' {threshold} =minimum free space
' If entered as an integer physical size is checked (in GB)
' If a decimal amount or an integer followed by "%"
' percentage free is checked.
' Examples: HDFree.vbs Comp1 20 -->Checks all volumes on Comp1 for 20GB free space.
' HDFree.vbs Comp2 10% -->Checks all volumes on Comp2 for 10% free space.
' HDFree.vbs Comp3 .15 -->Checks all volumes on Comp3 for 15% free space.
' HDFree.vbs Comp3 D:.15 -->Checks D: on Comp3 for 15% free space exclusively.
' No other drives will be checked.
' Returned status will be the D: drive free space
' figure in %.
' HDFree.vbs Comp3 D:5 -->Checks D: on Comp3 for 5GB free space exclusively
' No other drives will be checked.
' Returned status will be the D: drive free space
' figure in GB.
' HDFree.vbs Comp3 D:.15 20% -->Checks D: on Comp3 for 15% free space
' and all other drives for 20% free space.
' Returned status will be the free space figures
' of all drives.
' HDFree.vbs Comp3 C:.5 D:20 -->Checks C: for 5%, D: for 20GB free space.
' No other drives are checked.
' Returned status will be the free space
' figures of both drives.
' HDFree.vbs Comp3 C:.5 D:20 35% -->Checks C: for 5%, D: for 20GB and all other
' drives for 35% free space.
' Returned status will be the free space
' figures of all drives.
' Defaults: Local Computer (".") and 20%
'
' Output: [status]:{reply}
' [status] - Required. Format "scriptRes:{statusmsg}
' (see constants defined below)
' {reply} - Optional (on error this script always supplies one).
' May include simple description or system error codes
'
' NOTES: -This script has been modified to comply with (KS-Soft) Advanced Host Monitor's
' "shell script" method of monitoring.
' -Inspired by Glynn Seymours adaptation of Rob van der Woude's freespace.vbs
' http://www.robvanderwoude.com
'
' Modified Date: yyyy/mm/dd
' 2010/10/19
' ==========Begin Script==========
Option Explicit
DIM sCompStatus', sType, sResult, sSyntaxDesc
DIM iThreshold, iDfltThold, iCount, iTestType, iDrvTest, iTholdTest
DIM aThreshold()
' *** Default Values & constants
iDfltThold =.2
const statusAlive ="scriptRes:Host is alive:"
const statusDead ="scriptRes:No answer:"
const statusUnknown ="scriptRes:Unknown:"
const statusUnknownHost ="scriptRes:Unknown host:"
const statusOk ="scriptRes:Ok:"
const statusBad ="scriptRes:Bad:"
const statusBadContents ="scriptRes:Bad contents:"
const ShowSyntax ="/?"
iTholdTest = 0
iDrvTest = 0
' *** Parse the command-line arguments, check syntax, & perform necessary type conversions.
Select Case WScript.Arguments.Count
Case 0 ' *** No command line arguments
sCompStatus = ParseArg(".",0)
Case 1 ' *** Argument1 =computer name
sCompStatus = ParseArg(Wscript.Arguments(0),0)
Case Else ' *** Parse all remaining arguments
sCompStatus = ParseArg(Wscript.Arguments(0),0)
For iCount = 0 to WScript.Arguments.Count-2
iThreshold = ParseArg(Wscript.Arguments(iCount+1),1)
If InStr(iThreshold, ":") = 2 then
iDrvTest = iDrvTest + 1 ' How many drive test parameters
else
iTholdTest = 1 ' Default threshold parameter supplied
End If
' *** Add all arguments to array
redim preserve aThreshold(iCount)
aThreshold(iCount) = iThreshold
Next
End Select
' *** Determine test type
If iDrvTest = 0 and iTholdTest = 0 then iTestType = 1 ' Test all drives with default threshold
If iDrvTest = 0 and iTholdTest = 1 then iTestType = 2 ' Test all drives with specified threshold
If iDrvTest = 1 and iTholdTest = 0 then iTestType = 3 ' Test only one drive:threshold and return the free space value
If iDrvTest = 1 and iTholdTest = 1 then iTestType = 4 ' Test specified drive:threshold and all other drives with specified threshold
If iDrvTest > 1 and iTholdTest = 0 then iTestType = 5 ' Test only specified drives and return all results
If iDrvTest > 1 and iTholdTest = 1 then iTestType = 4 ' Test specified drive:threshold and all other drives with specified threshold
WScript.StdOut.Write HDFreeTest(sCompStatus, aThreshold)
' ===========End Script=========== '
' --------Functions & Subs--------
Function ParseArg(Arg, ArgNum)
' *** Purpose: Parse command-line arguments
Dim ParseOK : ParseOK = True
const Syntax ="Syntax: CSCRIPT HDFree.VBS {computer_name} {[drive:]threshold [[drive:]threshold] [...]}"
If InStr(Arg, "?") Then ArgNum =99
Select Case ArgNum
Case 0 ' *** sComputer Argument
ParseArg = CStr(Arg)
Case 1 ' *** Threshold Argument
On Error Resume Next
If InStr(Arg, ":") = 2 Then
ParseArg = Left(Arg, 2)
Arg = mid(Arg, 3)
ElseIf iTholdTest = 1 Then
ParseArg = statusUnknown & "Syntax: Only one default threshold value allowed: " & Arg
ParseOK = False
End If
If ParseOK Then
If IsNumeric(Arg) Then
ParseArg = ParseArg & Arg
ElseIf InStrRev(Arg,"%")<>0 Then
Arg = Trim(Left(Arg,InStrRev(Arg,"%")-1))/100
If Arg > .99 Then
ParseArg = statusUnknown & "Threshold value out of bounds: " & Arg * 100 & "%"
ParseOK = False
ElseIf ParseOK Then
ParseArg = ParseArg & Arg
End If
Else
ParseArg = statusUnknown & "Syntax: Argument conversion error: " & ParseArg & Arg
ParseOK = False
End If
End If
If (Arg <.01 or Arg >99) and ParseOK Then
ParseArg = statusUnknown & "Threshold value out of bounds: " & ParseArg
ParseOK = False
End If
Case Else ' *** Display script syntax
ParseArg = statusUnknown & Syntax
End Select
On Error Goto 0
If Not ParseOK Then
WScript.StdOut.Write ParseArg
Wscript.Quit
End If
End Function
' --------------------------------
Function HDFreeTest(ArgComp, ArgThold)
' *** Purpose: Query Windows servers (WMI) For available Hard Disk free space
DIM sStatus, sReply, sDrvName
DIM iFree, iThold, iTestThold, iDefinedThold, iSize
DIM oWMIService, oItem, aItems
DIM bLogicalDiskQuery
const GB=1073741824
bLogicalDiskQuery = False
' *** Set default threshold If supplied
For each iThold in ArgThold
If instr(iThold, ":") <> 2 then
iDefinedThold = CSng(iThold)
End If
Next
On Error Resume Next
Set oWMIService = Getobject("winmgmts://" & ArgComp & "/root/cimv2")
If Err.Number Then
HDFreeTest = statusUnknownHost & "Server not found or not responding: Error # " & _
CStr(Err.Number) & " " & Err.Description
Exit Function
End If
Set aItems = oWMIService.ExecQuery("Select * from Win32_Volume where DriveType =3",,48)
If Err.Number Then
HDFreeTest = statusUnknown & "Error # " & CStr(Err.Number) & " " & Err.Description
Exit Function
End If
For Each oItem in aItems 'Ugly test for returned items - XP doesn't support Win32_Volume
If Err.Number Then
Err.Clear
bLogicalDiskQuery = True
Exit For
End If
Exit For
Next
If bLogicalDiskQuery Then
Set aItems = oWMIService.ExecQuery("Select * from Win32_LogicalDisk where DriveType =3",,48)
else
Set aItems = oWMIService.ExecQuery("Select * from Win32_Volume where DriveType =3",,48)
End If
If Err.Number Then
HDFreeTest = statusUnknown & "Error # " & CStr(Err.Number) & " " & Err.Description
Exit Function
End If
On Error GoTo 0
sStatus = statusOK
For Each oItem in aItems
If bLogicalDiskQuery Then
iSize = oItem.Size
sDrvName = oItem.Name
Else 'Win32_Volume returns drive name with a trailing backspace and mounted volumes as drive:\path
iSize = oItem.Capacity
sDrvName = oItem.Name
If Len(sDrvName) > 3 Then 'Mount point
sDrvName = Replace(sDrvName, "\\?\", "")
sDrvName = Replace(Replace(sDrvName, ":\", "-"), "\", ":")
Else
sDrvName = Replace(sDrvName, ":\", ":")
End If
End If
Select Case iTestType
Case 1 ' Test all drives with default threshold
iTestThold = iDfltThold
If sReply <> "" Then sReply = sReply & ", "
iFree =Int(.5+(100 * oItem.freespace / iSize))
If iFree<iTestThold*100 Then sStatus = statusBad
sReply = sReply & sDrvName & iFree & "%" & "(" & Round(oItem.freespace / GB,2) & ")"
Case 2 ' Test all drives with specified threshold
iTestThold = iDefinedThold
If sReply <> "" Then sReply = sReply & ", "
iFree =Int(.5+(100 * oItem.freespace / iSize))
If iTestThold <1 Then
If iFree<iTestThold*100 Then sStatus = statusBad
sReply = sReply & sDrvName & iFree & "%" & "(" & Round(oItem.freespace / GB,2) & ")"
Else
If Round(oItem.freespace / GB,2)<iTestThold Then sStatus = statusBad
sReply = sReply & sDrvName & Round(oItem.freespace / GB,2) & "(" &iFree & "%" & ")"
End If
Case 3 ' Test only one drive:threshold and return the free space value
For each iThold in ArgThold
If Ucase(left(iThold, 2)) = Ucase(sDrvName) then
iTestThold = CSng(mid(iThold, 3))
iFree =Int(.5+(100 * oItem.freespace / iSize))
If iTestThold < 1 Then
If iFree<iTestThold*100 Then sStatus = statusBad
sReply = """" & sReply & iFree & " %"""
Else
If Round(oItem.freespace / GB,2)<iTestThold Then sStatus = statusBad
sReply = """" & sReply & Round(oItem.freespace / GB,2) & " GB"""
End If
End If
Next
Case 4 ' Test specified drive:threshold and all other drives with specified threshold
If sReply <> "" Then sReply = sReply & ", "
iTestThold = iDefinedThold
For each iThold in ArgThold
If Ucase(left(iThold, 2)) = Ucase(sDrvName) then
iTestThold = CSng(mid(iThold, 3))
End If
Next
iFree =Int(.5+(100 * oItem.freespace / iSize))
If iTestThold <1 Then
If iFree<iTestThold*100 Then sStatus = statusBad
sReply = sReply & sDrvName & iFree & "%" & "(" & Round(oItem.freespace / GB,2) & ")"
Else
If Round(oItem.freespace / GB,2)<iTestThold Then sStatus = statusBad
sReply = sReply & sDrvName & Round(oItem.freespace / GB,2) & "(" &iFree & "%" & ")"
End If
Case 5 ' Test only specified drives and return all results
For each iThold in ArgThold
If Ucase(left(iThold, 2)) = Ucase(sDrvName) then
If sReply <> "" Then sReply = sReply & ", "
iTestThold = CSng(mid(iThold, 3))
iFree =Int(.5+(100 * oItem.freespace / iSize))
If iTestThold < 1 Then
If iFree<iTestThold*100 Then sStatus = statusBad
sReply = sReply & sDrvName & iFree & "%" & "(" & Round(oItem.freespace / GB,2) & ")"
Else
If Round(oItem.freespace / GB,2)<iTestThold Then sStatus = statusBad
sReply = sReply & sDrvName & Round(oItem.freespace / GB,2) & "(" &iFree & "%" & ")"
End If
End If
Next
End Select
Next
If sReply = Empty Then
HDFreeTest = statusUnknown & "Local Hard Disk(s) not found"
Else
HDFREETest = sStatus & sReply
End If
End Function |
cheers, Paul
Last edited by Paul_NHS on Wed Oct 20, 2010 2:19 am; edited 7 times in total |
|
Back to top |
|
|
greyhat64
Joined: 14 Mar 2008 Posts: 246 Location: USA
|
Posted: Mon Mar 02, 2009 4:24 pm Post subject: |
|
|
Paul,
Good work! Two things:
1. I like what you've done, but what did you think of my idea to 'bury' the passing of 'Bad Argument' results in the ParseArg function? (see previous response)
2. Good find on the "shell script" handles issue. I think I read somewhere that the actual limit is 6, but it probably starts choking before then.
(Not your fault, but. . .) I hate the solution!
I've set up my tree/folders to match our distributed reporting structure, and I have folder level variables set for notifying the tech(s) responsible for that server/server group. This way one alert profile takes care of it all. If I move all disk space checks into one folder I'm back to square one with that.
Why should I have to restructure my test environment to accommodate a known limitation?
NOTE: If this 'non-simultaneous' option were inheritable I could live with it because it wouldn't force me to change my folder structure.
Other possibilities:
1. Use Active Agents on all the servers. If you prefer the server to run most of the testlist you could limit the agent to only running shell scripts.
- In my environment, seldom will any individual server have more than five shell scripts.
- Some people (myself included) prefer agentless operations where possible - but it's an option.
(Thinking off the top of my head)
2. Use a 'master' shell script (???). Keep a count of running shell scripts. Similar to: Code: | Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Process WHERE Name='cscript.exe'") | On second thought, it probably wouldn't work.
- While enabling/disabling tests based on colItems.Count, or executing a wait cycle could prevent additional tests from being launched, it wouldn't prevent simultaneous starts.
- I feel like there is potential here I can't put my finger on it.
3. Go 'Old School'. Use prime numbers for your schedules
- Test every 7min/2sec, 7min/23sec, 11min/5sec, 11min/17sec, . . .). Set each test individually, or create small 'test groups' with the same schedule to minimize overlap.
- This is ugly and would take a bit of planning and manual manipulation. |
|
Back to top |
|
|
greyhat64
Joined: 14 Mar 2008 Posts: 246 Location: USA
|
Posted: Mon Mar 02, 2009 4:28 pm Post subject: |
|
|
MY OPINION:
Knowing the limitations of this method, AHM should manage this by default without resorting to the "non-simultaneous test execution" trickery you describe.
- The "non-simultaneous test execution" option should be employed to manage other types of dependecies/deficiencies that do NOT have an easily identifiable limitation.
- The AHM application/service could actively keep a count of all running shell script tests and throttle a pending test if the count of actively running scripts reaches the threshold.
- Making this folder level setting inheritable would be a mistake (all tests in the branch would become non-simultaneous) unless you could 'tag' tests as being a member of a non-simultaneous execution group, accomplishing what you have done by putting them all in a separate folder.
Your thoughts. . .
If you agree I'll post a "Wish List" item & tag this thread. |
|
Back to top |
|
|
KS-Soft
Joined: 03 Apr 2002 Posts: 12801 Location: USA
|
Posted: Mon Mar 02, 2009 4:47 pm Post subject: |
|
|
Normally HostMonitor may perform many Shell Script tests at the same time however this may depend on external programs limitations used by the test
Regards
Alex |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|