Issue creating a script with dual logic in deeming a website online

I am currently trying to create a script that allows me to check multiple web url’s in order to see if they are online and active. My company has multiple servers with different environments active (Production, Staging, Development etc.) I need a script that can check all the environments URL’s and tell me whether or not they are online each and every morning so I can be ahead of the game in addressing any servers or websites being down.

My issue however is I can’t solely base the logic strictly on an HTTP code to deem the site online or not, some of our websites may be online from an HTTP standpoint but have components or webparts of the site that is down displaying an error message on the page.

I am having trouble coming up with a script that can not only check the HTTP status as well as scan the page and parse out any error messages and then write to host based on both pieces of logic whether or not the site is “Online” or “Down”

Here is what I have so far, you will notice it does not include anything regarding parse for key words as I don’t know how to implement…

#Lower Environments Checklist Automated Script

Write-Host Report generated at (Get-date)

write-host(“Lower Environments Status Check”);

$msg = “”
$array = get-content C:\LowerEnvChecklist\appurls.txt
$log = “C:\LowerEnvChecklist\lowerenvironmentslog.txt”

write-host(“Checking appurls.txt…One moment please.”);

("`n--------------------------------------------------------------------------- ") | out-file $log -Append

Get-Date | Out-File $log -Append

(“`nChecking Links”) | out-file $log -Append
(“`n”) | out-file $log -Append

for ($i=0; $i -lt $array.length; $i++) {
$HTTP_Status = -1
$HTTP_Request = [System.Net.WebRequest]::Create($array[$i])
$HTTP_Request.Timeout =60000
$HTTP_Response = $HTTP_Request.GetResponse()
$HTTP_Status = [int]$HTTP_Response.StatusCode

If ($HTTP_Status -eq 200) { 
$msg =  $array[$i] + " is ONLINE!" 
}
Else {
$msg = $array[$i] + " may be DOWN, please check!"
}
$HTTP_Response.Close()
$msg | Out-File $log -Append -width 120
write-host $msg

}

(“`n”) | out-file $log -Append
(“`nLower Environments Checklist Completed”) | out-file $log -Append

write-host(“Lower Environments Checklist Completed”);

appurls.txt just contains the internal URLs I need checked FYI.

Any help would be much appreciated! Thanks.

Will this script run on a client computer, or on a server?

Hello Don,

It will be run from my local PC every morning, currently executing from the C: drive.

The error messages that would need to be included in the logic are:
“An error has occurred”
“Oops” “Unable to display widget data”
“An unexpected error occurred”
“temporarily unavailable”

So, one of the neat things about Invoke-WebRequest on a client is that the return object contains not only the raw web page text, but also a set of collections representing various portions of the web page.

In the simplest form, you could probably just do a wildcard match. Assuming you have the raw content in $raw…

switch -wildcard ($raw) {
An error has occurred” { # this }
Oops” { # that }
}

And so on. Depending on the exact structure of the web page, the collections produced by Invoke-WebRequest might make it even easier. Now, you’re manually using a .NET WebRequest object, which is fine. Invoke-WebRequest does the same thing, it just does a little more work for you with the result. What you’re doing provides you with the raw text, too, if you want to keep doing it that way.

Cool, I didn’t know that there was a wildcard option - so I guess my last question would be - How would you incorporate that logic into what I already have? Or would you lay out the script in a totally different way to get what I’m trying to achieve? I’m very new to this so I don’t have any issue with you telling me my current script is not the way to go for what I need big picture. Thanks for the help by the way, much appreciated!

help about_switch - it’s pretty flexible.

So, pseudo-logic:

  • Run the web request.

  • Check the status code. If you didn’t get a 200, you’re not going to have any raw content, and you have an HTTP-level error.

  • If you got a 200, do the wildcard comparison of the raw content to see if the web page text contained one of your error messages.

  • Create log, on-screen messages, or whatever.

Given that i’m checking 10+ web pages in this script, how would the switch logic know how to match an error to the correct web page it got it from? I get the logic behind the switch command i’m just not sure if I can easily implement it with what I already have.

OK, maybe a little less-pseudo :). First, understand that your approach is going to look a lot different from mine, because your code is a lot more like writing C# in Visual Studio, and less like native PowerShell. I’m more familiar with native PowerShell, hence the difference.

$sites = @('http://one','http://two','http://three')
foreach ($site in $sites) {
  $response = Invoke-WebRequest $site
  if ($response.statuscode -eq 200) {
    switch -wildcard ($response.content) {
      "*oops*" { # do something }
    }
  } else {
    # HTTP request failed
  }
}

The point is that you’re only checking one web page at a time. That way you can have a unique response for each one. You technically should have been doing that in your original code, really. Invoke-WebRequest forces you into it, because the -Uri parameter doesn’t accept an array - it only accepts a single address.

When messing around with that setup I keep getting this error:

The term ‘Invoke-WebRequest’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling
of the name, or if a path was included, verify that the path is correct and try again.
At line:3 char:32

  • $response = Invoke-WebRequest <<<< $site
    • CategoryInfo : ObjectNotFound: (Invoke-WebRequest:String) , CommandNotFoundException
    • FullyQualifiedErrorId : CommandNotFoundException

After some research, looks like that cmdlet is only available for PowerShell 3.0, unfortunately our company has not yet upgraded to that on an enterprise level yet. Still stuck with 2.0 - back to the drawing board?

I’ve upgraded to 3.0 however im still having issues with the above approach, the Else statement in the script you gave is giving me a hard time:

Else : The term ‘Else’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a
path was included, verify that the path is correct and try again.
At line:25 char:3

  • Else {
  • + CategoryInfo          : ObjectNotFound: (Else:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
    
    

Else : The term ‘Else’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a
path was included, verify that the path is correct and try again.
At line:25 char:3

  • Else {
  • + CategoryInfo          : ObjectNotFound: (Else:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException</code>

Everything there should work in 2.0. There’s likely a syntax error or unclosed brace or something in the code you’ve typed - unfortunately, I’m not going to be at a computer where I can run PowerShell to help you out with that. “Else” is very much a real keyword when used in conjunction with If, ever since PowerShell 1.0 (https://technet.microsoft.com/en-us/library/hh847876.aspx); you’ve very likely got a syntax error at some point.

Also, the code I posted was not intended as a complete solution. You’re still going to have to verify it - if you’re just planning to cut-and-paste it, sorry, that wasn’t my intent ;). I just wanted to try and help you understand the structure you’d need.

I’ve figured most of it out, just now having issues logging it properly, my previous script used an array to help with the logging. Trying to get it to work, here’s what I have so far:

#Lower Environments Checklist Automated Script

Write-Host Report generated at (Get-date)

write-host(“Lower Environments Status Check”);

$log = “C:\LowerEnvChecklist\lowerenvironmentslog.txt”
$sites = @(‘http://google.com’,‘http://google.ca’)
$msg = “”

write-host(“Checking Lower Environments, One moment please.”);

(“`n---------------------------------------------------------------------------”) | out-file $log -Append

Get-Date | Out-File $log -Append

(“`nChecking Links”) | out-file $log -Append
(“`n”) | out-file $log -Append

foreach ($site in $sites) {
$response = Invoke-WebRequest $site

If ($response.statuscode -eq 200) {
switch -wildcard ($response.content) {
oops” {$msg = " may be DOWN, please check!“}
}
If ($response.statuscode -eq 201, 202, 203, 204, 400, 401, 402, 403, 404, 500, 501, 502, 503) {
$msg = " may be DOWN, please check!”
}
Else{$msg = " is ONLINE!"

}
$msg | Out-File $log -Append -width 120
write-host $msg

}

(“`n”) | out-file $log -Append
(“`nLower Environments Checklist Completed”) | out-file $log -Append

write-host(“Lower Environments Checklist Completed”);

}

In the logfile I need the msg’s defined to show up next to the URLs being checked.