Want to keep an eye on how your servers are doing? Here's a guide on using PowerShell to get yourself started in the right direction.

When you need to ensure a server stays online with all of the required services running there are lots of different tools to make this happen both big and small. All of these tools work, but all are built with the generic user in mind. None of these off-the-shelf tools are built with your company's unique requirements in mind.

Building your own server monitor tools is no simple task and will require effort, but you'll soon see that by using PowerShell and some determination, you'll be able to forego spending thousands of dollars on a product and, eventually, have some monitors that work exactly to your specification. You'll also learn a lot more about PowerShell scripting in the process which is always a good thing!

Before we can start building code, we must first determine how we're going to build this tool. A monitor of any sort has five elements; a trigger, an action, a known good state, a known bad state and optionally an output of some kind.

For example, a trigger could be a specific time, the action may be to send an ICMP request to the server, the known good state would be if it responds, the known bad state would be if it does not respond and the output might be sending an email to the administrator notifying them of the threshold. To build a great monitor of any kind, not just PowerShell, all of these elements must be incorporated into the tool in some way.

To demonstrate how to create simple server monitors in PowerShell, let's pick a couple of examples. Let's say I have a web server that needs to be up 24/7. It needs to have a specific Windows service running, and it always needs to always respond on TCP port 80. What are some example elements in play here?

Monitor #1

Trigger: Every 5 minutes
Action: Get Windows service state
Bad State: Not running
Good State: Running
Output: Send an email to administrator

Monitor #2

Trigger: Every 5 minutes
Action: Connect to TCP port 80
Bad State: No response
Good State: HTTP/200
Output: Send an email to administrator

Each performance monitor can be built into a PowerShell function. I'll put these functions inside of a script called C:\Monitors.ps1.

function Test-WindowsService {
     param(
         [Parameter(Mandatory)]
         [string]$ComputerName,
 
         [Parameter(Mandatory)]
         [string]$Name,
 
         [Parameter(Mandatory)]
         [string]$GoodState = 'Running',
 
         [Parameter(Mandatory)]
         [string]$BadState = 'Stopped'
     )
 
     $service = Get-Service -ComputerName $ComputerName -Name $Name
     switch ($service.Status) {
         $GoodState {
             $true
             break
         }
         $BadState {
             $false
             break
         }
         default {
             throw "Unrecognized service state: [$_]"
         }
     }
 }
 
 function Test-Http {
     param(
         [Parameter(Mandatory)]
         [string]$ComputerName,
 
         [Parameter(Mandatory)]
         [int]$GoodResponse = 200,
 
         [Parameter(Mandatory)]
         [ValidateSet('AnythingButGoodResponse')]
         [string]$BadResponse = 'AnythingButGoodResponse'
     )
 
    $response = Invoke-WebRequest -Uri $ComputerName -UseBasicParsing
     if ($response.StatusCode -eq $GoodResponse) {
         $true
     } elseif ($BadResponse -eq 'AnythingButGoodResponse') {
         $false
     }
 }

Now that we have two performance monitors built, we can build an invocation script to call these monitors and perform other tasks with them. I'll create a script called C:\CallMonitors.ps1 which will look like this:

## Dot source the functions to make them available
 
 . C:\Monitors.ps1
 
 ## Define the server(s) we'll be monitoring and the criteria
 $monitors = @(
     @{
         ServerName = 'SRV1'
         Monitor = 'HTTP'
         Report = 'Email'
     }
     @{
         ServerName = 'SRV1'
         Monitor = 'WindowsService'
         Parameters = @{
             Name = 'wuauserv'
         }
         Report = 'Email'
     }
     @{
         ServerName = 'SRV2'
         Monitor = 'HTTP'
         Report = 'Email'
     }
 )
 
 foreach ($m in $monitors) {
     $funcParams = $m.Parameters
     if (-not (& "Test-$($_.Monitor)" @funcParams -ComputerName $m.ServerName)) {
         if ($m.Report -eq 'Email') {
             Send-MailMessage -To '[email protected]' -Subject '{0} monitor failed on {1} -f $m.Monitor,$m.ServerName
         }
     }
 }

Notice how everything has a specific structure. All monitors are in an array of hashtables with each attribute necessary. Once the monitor information is in a structure like this, we can easily apply the rules to each by looping over each one in a loop. Schedule a task to call this script every 5 minutes, and you're golden to monitor your server performance!

Conclusion

The examples provided were just that, examples. Pay attention to the style and how to build the framework; not necessarily the monitors themselves. By replicating a framework like this, you'll be able to monitor just about anything in your environment!

Further Reading

Join the Jar Tippers on Patreon

It takes a lot of time to write detailed blog posts like this one. In a single-income family, this blog is one way I depend on to keep the lights on. I'd be eternally grateful if you could become a Patreon patron today!

Become a Patron!