OpsMgr: Monitoring File Content with a Powershell-based Monitor
><]]]°> <°[[[>< ><]]]°> <°[[[>< <°[[[>< ><]]]°> <°[[[>< <°[[[>< ><]]]°>
This post features an example of a file content monitor that was created with the Powershell-based monitor (PBM) type and wizard (Download sample).
In this example, a file content monitor to look for and alert on ASCII animals (ASCIImals ?) found in a sample file, was created.
The sample file contains the following combination of characters and was placed on a specific drive of an agent managed computer:
The alert and state change recorded are as follows:
But what if the sample file contains a slight variation to the search pattern used, example as follows:
The script used was able to do an estimate of the least amount of matches found. Hence, the alert and state change recorded are as follows:
<°[[[>< ><]]]°> ><]]]°> <°[[[>< <°[[[>< <°[[[>< ><]]]°> ><]]]°> <°[[[>< ><]]]°> <°[[[>< ><]]]°> <°[[[><
Now, lets see how this File Content Monitor was configured:
For this Powershell-based unit monitor, the following values were used in General Properties.
Note: This monitor targets the Windows Server class, and hence will find and check the samples files located in all agent management computer of the management group.
The Powershell script used by this monitor was modified to return its output in a Propertybag.
Building expressions based on the value in the Propertybag and mapping monitor conditions to health states were very straight forward. The Expression Builder Pages builds expression that looks for a particular value from the Propertybag that the data source outputs (Property[@Name='State'] ).
The name of the value in the Propertybag was specified in the alert context variable: $Data/Context/Property[@Name='Description'] $
Here is the script used:
This script searches the sample test file for combinations of characters that matches the patterns specified at the top of the script.
#Sample script start
$fileName= "c:\SampleTestFile.txt"
$fishCount = 0
$pattern4fish1 = "<*\[\[\[><"
$pattern4fish2 = "><]]]*"
$frogCount = 0
$pattern4frog1 = "@..@"
$pattern4frog2 = "(----)"
$pattern4frog3 = "\/_> <_\\"
$possumCount = 0
$pattern4possum1 = "(\\__/)"
$pattern4possum2 = "(=0.0=)"
$pattern4possum3 = '\(\"\)_\(\"\)'
$API = new-object -comObject "MOM.ScriptAPI"
$PropertyBag = $API.CreatePropertyBag()
$FullList=""
$newline = "`r`n"
if(Test-Path -path $fileName) {
###Look for fish###
select-string -path $filename -pattern $pattern4fish1 -allmatches | ForEach {$fishToLeft = 0} {$fishToLeft += $_.Matches.count}
select-string -path $filename -pattern $pattern4fish2 -allmatches | ForEach {$fishToRight = 0} {$fishToRight += $_.Matches.count}
$fishCount = $fishToLeft + $fishToRight
$FullList = "There are " + $fishCount + " fish found in " + $fileName + ", " + $fishToLeft + " looking to the left and " + $fishToRight + " looking to the right. " + $newline
###Look for possums###
select-string -path $filename -pattern $pattern4possum1 -allmatches | ForEach {$possumPart1 = 0} {$possumPart1 += $_.Matches.count}
select-string -path $filename -pattern $pattern4possum2 -allmatches | ForEach {$possumPart2 = 0} {$possumPart2 += $_.Matches.count}
select-string -path $filename -pattern $pattern4possum3 -allmatches | ForEach {$possumPart3 = 0} {$possumPart3 += $_.Matches.count}
if($possumPart1 -eq $possumPart2 -and $possumPart1 -eq $possumPart3 -and $possumPart2 -eq $possumPart3) {
$FullList += "There are " + $possumPart1 + " possums found in " + $fileName + ". " + $newline }
else {
if($possumPart1 -and $possumPart2 -and $possumPart3 -ne 0) {
[int[]] $arr = $possumPart1,$possumPart2,$possumPart3
$possumEstimate = $arr | sort-object | select -first 1
$FullList += "Guess-timating there would be at least " + $possumEstimate + " possum(s) of the required type in " + $fileName + ". " + $newline }
else
{$FullList += "No luck finding a complete possum in " + $fileName + ". " + $newline }
}
###Look for frogs###
select-string -path $filename -pattern $pattern4frog1 -allmatches | ForEach {$FrogPart1 = 0} {$FrogPart1 += $_.Matches.count}
select-string -path $filename -pattern $pattern4frog2 -allmatches | ForEach {$FrogPart2 = 0} {$FrogPart2 += $_.Matches.count}
select-string -path $filename -pattern $pattern4frog3 -allmatches | ForEach {$FrogPart3 = 0} {$FrogPart3 += $_.Matches.count}
if($FrogPart1 -eq $FrogPart2 -and $FrogPart1 -eq $FrogPart3 -and $FrogPart2 -eq $FrogPart3) {
$FullList += "There are " + $FrogPart1 + " frogs found in " + $fileName + ". " + $newline }
else {
if($FrogPart1 -and $FrogPart2 -and $FrogPart3 -ne 0) {
[int[]] $arr = $FrogPart1,$FrogPart2,$FrogPart3
$FrogGuesstimate = $arr | sort-object | select -first 1
$FullList += "Guess-timating there would be at least " + $FrogGuesstimate + " frog(s) of the required type in " + $fileName + ". " + $newline }
else
{$FullList += "No luck finding a complete frog in " + $fileName + ". " +$newline }
}
}
if($FullList -eq "")
{ $PropertyBag.AddValue("State","OK")
$PropertyBag.AddValue("Description", "Nothing found !") }
else
{ $PropertyBag.AddValue("State","FLAG")
$PropertyBag.AddValue("Description", $FullList) }
$PropertyBag
Points to note:
The select-string is the key cmdlet used to get the number of string matches and occurrences in the sample file.
The sort-object cmdlet was very useful to find the smallest number in a list of integers.
Escape characters (“\”) are used to handle special characters in the string pattern.
><]]]°> <°[[[>< <°[[[>< ><]]]°> <°[[[>< ><]]]°> ><]]]°> <°[[[>< <°[[[>< ><]]]°> ><]]]°> <°[[[><