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

This topic contains 14 replies, has 2 voices, and was last updated by  Adam Beers 1 year, 10 months ago.

  • Author
    Posts
  • #33245

    Adam Beers
    Participant

    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

    ("`n***Checking 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
    ("`n***Lower 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.

  • #33246

    Don Jones
    Keymaster

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

  • #33248

    Adam Beers
    Participant

    Hello Don,

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

  • #33249

    Adam Beers
    Participant

    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"

  • #33251

    Don Jones
    Keymaster

    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.

  • #33253

    Adam Beers
    Participant

    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!

  • #33255

    Don Jones
    Keymaster

    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.

  • #33257

    Adam Beers
    Participant

    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.

  • #33258

    Don Jones
    Keymaster

    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.

  • #33260

    Adam Beers
    Participant

    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

  • #33262

    Adam Beers
    Participant

    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?

  • #33267

    Adam Beers
    Participant

    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

  • #33272

    Don Jones
    Keymaster

    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.

  • #33273

    Don Jones
    Keymaster

    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.

  • #33274

    Adam Beers
    Participant

    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

    ("`n***Checking 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
    ("`n***Lower 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.

You must be logged in to reply to this topic.