I run a self-hosted WordPress blog here as part of a hosted package. I run this on a very tight budget so I'm pretty sure I share resources with other tenants. This means that sometimes the server is unavailable, usually for only a brief period of time. I have the JetPack WordPress plugin configured to monitor when the site is up or down. But I thought I'd add another layer of testing using PowerShell.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
Fellow MVP Chrissy LeMaire sent me a message on Twitter that my blog was down with a link to the web site http://downforeveryoneorjustme.com. What I liked about the site is that it produces a very simple page. Once I saw that I realized I could use Invoke-Webrequest and build a simple PowerShell function to scrape the page results.
It is very easy to get the page.
$w = Invoke-Webrequest "http://downforeveryoneorjustme.com/blog.jdhitsolutions.com" -DisableKeepAlive
The resulting object will include the parsedHTML as a property. I knew from looking at the page source in my browser that the information I wanted was in a DIV tag with an ID property called "container".
With this information I can use the getElementbyID() method to get this item.
$x = $w.ParsedHtml.getElementById("container")
Fortunately there is only a single result for this ID. If there had been several I would have had to include additional filtering code. All I need to do is look at the InnerText property.
I can refine this by getting just the first line.
I now have a few commands that work. Time to build a function around them so I have an easy, re-usable tool. I have put the script file as a gist on GitHub.
#requires -version 4.0 # get most current version at https://gist.github.com/jdhitsolutions/3046b3aafcbd89a6d857f7a7a5586e47 Function Test-UporDown { <# .Synopsis Test if a web site is down or if it is just you. .Description The function uses the web site DownForEveryoneOrJustme.com to test is a web site or domain is up or down, or if the problem is just you. The command will write a custom object to the pipeline. See examples. .Parameter Name The name of a web site or domain such as google.com or powershell.org. .Parameter UseUniversalTime Convert the tested date value to universal or GMT time. .Example PS C:\> test-upordown pluralsight.com Name IsUp Date ---- ---- ---- pluralsight.com True 12/22/2016 9:17:00 AM .Example PS S:\> test-upordown pluralsight.com -UseUniversalTime Name IsUp Date ---- ---- ---- pluralsight.com True 12/22/2016 2:17:41 PM .Example PS S:\> test-upordown foofoo.edu -Verbose VERBOSE: [BEGIN ] Starting: Test-UporDown VERBOSE: [PROCESS] Testing foofoo.edu VERBOSE: GET http://downforeveryoneorjustme.com/foofoo.edu/ with 0-byte payload VERBOSE: received 2256-byte response of content type text/html;charset=utf-8 VERBOSE: [PROCESS] It's not just you! http://foofoo.edu looks down from here. VERBOSE: [END ] Ending: Test-UporDown Name IsUp Date ---- ---- ---- foofoo.edu False 12/22/2016 9:19:13 AM .Notes version: 1.0 Learn more about PowerShell:Essential PowerShell Learning Resources.Link Invoke-WebRequest #> [cmdletbinding()] Param( [Parameter( Position = 0, Mandatory, HelpMessage = "Enter a web site name, such as google.com.", ValueFromPipeline )] [ValidateNotNullorEmpty()] [ValidateScript({ $_ -notmatch "^http"})] [string]$Name, [Switch]$UseUniversalTime ) Begin { Write-Verbose "[BEGIN ] Starting: $($MyInvocation.Mycommand)" } #begin Process { Write-Verbose "[PROCESS] Testing $Name" $response = Invoke-WebRequest -uri "http://downforeveryoneorjustme.com/$Name/" -DisableKeepAlive #get the result text from the HTML document $text = $response.ParsedHtml.getElementById("container").InnerText #the first line has the relevant information that looks like this: # It's just you. http://blog.jdhitsolutions.com is up $reply = ($text -split "`n" | Select -first 1) Write-Verbose "[PROCESS] $reply" If ($UseUniversalTime) { Write-Verbose "[PROCESS] Using universal time (GMT)" $testDate = (Get-Date).ToUniversalTime() } else { $testDate = Get-Date } #write a result object to the pipeline [pscustomObject]@{ Name = $Name IsUp = $reply -match "\bis up\b" Date = $TestDate } } #process End { Write-Verbose "[END ] Ending: $($MyInvocation.Mycommand)" } #end } #define an optional alias Set-Alias -Name tup -Value Test-UporDown
The script also includes an alias. I also added a parameter to return the tested date time in GMT should you need that.
Now, it is very easy to test if a site is up or down.
I'm not sure what sort of monitoring and reporting tool I'll build with this, but hopefully it will be worth blogging about. In the mean time, give this a shot and let me know what you think. If you run into problems with the code, please post something in the discussion section on the Gist page.