- Create a certificate-signed RDP shortcut via Group Policy - Fri, Aug 9 2019
- Monitor web server uptime with a PowerShell script - Tue, Aug 6 2019
- How to build a PowerShell inventory script for Windows Servers - Fri, Aug 2 2019
Overview
In this article, we're going to build a PowerShell script that will query a web service and capture its HTTP status code. If the status code is 200 (OK), we're going to assume all is well. Otherwise, we'll assume that the web service is down and take action.
Since a monitor isn't a one-time thing, we're going to create a scheduled task to run this script in so that the web service can be monitored at a regular interval.
Let's dig in!
Querying a web service
The first task we need to do is come up with the code to query a web server and get it to return the HTTP status code. One of the easiest ways to do that is to use the Test-NetConnection cmdlet. This cmdlet allows you to attempt to connect to any port on a remote computer and confirm whether or not the connection was successful.
You can run the Test-NetConnection command by providing it the ComputerName and CommonTCPPort of HTTP to force it to test port 80 on a web server.
Test-NetConnection -ComputerName 10.0.0.5 -CommonTCPPort HTTP
Once you know the port is open, you can test the HTTP status code using Invoke-WebRequest.
PS51> $response = Invoke-WebRequest -Uri http://server -UseBasicParsing PS51> $response.StatusCode 200
At this point, you can build an up/down scenario with 200 being "up" and not 200 being "down."
if ($response.StatusCode -ne 200) { $false } else { $true }
Creating a test script
Now take the code we just covered and add it into a script. Since it's good to only build reusable scripts, create parameters for the URL so you can provide different URLs if needed.
param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$Url ) ## Parse host from URL $hostname = $url.split('/')[2] if (-not (Test-NetConnection -ComputerName $hostname -CommonTCPPort HTTP).TcpTestSucceeded) { $false } else { $response = Invoke-WebRequest -Uri $url -UseBasicParsing if ($response.StatusCode -ne 200) { $false } else { $true } }
You now have a script you can test a web service's response on by running:
PS51> .\Test-WebService.ps1 -Url 'http:\\webserver'
You still don't have any action taken if the monitor is down. The action can be anything since we're writing PowerShell. A common action to take is sending an email, so you can reference Send-MailMessage if the status code is not 200 like below.
This would be done in another script or via the console. I don't recommend putting the action in the test script because you always want them to be decoupled from other tasks as much as possible.
PS51> if (.\Test-WebService.ps1 -Url 'http:\\webserver') { Send-MailMessage ## parameters }
Creating a scheduled task
A monitor doesn't do much good unless it fires more than once. Let's set up a Windows scheduled task to kick off this PowerShell script at a regular interval.
So we don't have to leave the PowerShell console, download a pre-made script called New-ScheduledScript from the PowerShell Gallery via Install-Script New-ScheduledScript -Force. Before you create the scheduled task, check that it doesn't already exist on the server.
I'll use PowerShell Remoting to run Get-ScheduledTask on that remote server. I'll call this scheduled task Web Service Monitor.
PS51> Invoke-Command -ComputerName <server> -ScriptBlock { Get-ScheduledTask -TaskName 'Web Service Monitor' }
If you receive an error about the task not being found, that's a good thing!
Next, build all of the parameters required to pass to the New-ScheduledScript script downloaded earlier. In this example, my test script is at C:-WebService.ps1, and I'd like to execute this script from the C:folder on the remote server.
$parameters = @{ ScriptFilePath = 'C:\Testing\Test-WebService.ps1' LocalScriptFolderPath = 'C:\Testing
The scheduled task will run every day at 3AM.
TaskTriggerOptions = @{ 'Daily' = $true 'At' = '3Am' }
We'll name it Web Service Monitor and run it under a username of adminuser that's local to the remote server. This user's password is password12.
TaskName = 'Web Service Monitor' TaskRunAsUser = 'adminuser' TaskRunAsPassword = 'password12'
The server that will be executing the testing script is called SRV1. I'll configure the scheduled task to pass a URL of http://webserver to our Test-WebService.ps1 script that will be on the remote server.
Computername = 'SRV1' ScriptParameters = "-Url http://webserver"
Bring all of these parameters in a single hash table for splatting, and you get:
$parameters = @{ ScriptFilePath = 'C:\Testing\Test-WebService.ps1' LocalScriptFolderPath = 'C:\Testing' TaskTriggerOptions = @{ 'Daily' = $true 'At' = '3Am' } TaskName = 'Web Service Monitor' TaskRunAsUser = 'adminuser' TaskRunAsPassword = 'password12' Computername = 'SRV1' ScriptParameters = "-Url http://webserver" }
Now pass the parameters to the New-ScheduledScript.ps1 script to create the scheduled task.
PS51> New-ScheduledScript.ps1 @parameters
Then, verify that the scheduled task is created on the remote server using the Get-ScheduledTask cmdlet you used before.
Invoke-Command -ComputerName -ScriptBlock { Get-ScheduledTask -TaskName 'Web Service Monitor' }
You should now be returned a scheduled task object.
Running manually
At this point, the scheduled task will execute every day at 3AM. To test it manually, however, you can invoke the scheduled task using the Start-ScheduledTask cmdlet, as shown below.
Subscribe to 4sysops newsletter!
PS51> Invoke-Command -ComputerName SRV1 -ScriptBlock { Start-ScheduledTask -TaskName 'Web Service Monitor' }
If you've set up the action to send an email, create a file, restart a service, or some other task, the said task will be executed if the web service doesn't return an HTTP status code of 200.