I’ve been having some problems with my server recently. If it restarts, because of windows update or for whatever reason, some of my websites can fail to start. I think it might be because WAS was configured as a manually started service, but I’m not sure. I wanted to be warned if any of the sites on my machine were down, and for an automatic restart to be attempted if they were.
I’ve written a little Powershell script to do this. It was an interesting exercise because one of the things that I wanted to do was get an email via my Google Apps account.
Am I insane? Is there a far easier and more obvious way of doing this? Let me know in the comments.
Here’s the script (and yes, I’m a total Powershell Noob :)
$fromAddress = "someServer@suteki.co.uk" $toAddress = "mike.hadlow@suteki.co.uk" $subject = "One or more websites are not responding" $port = 587 $monitorPassword = "s0meN1cePa33w0rd" $sites = @{ "suteki.shop" = "http://suteki.shop/"; "blue.shop" = "http://green.shop/" } # send an email message via gmail function SendMessage([string]$body) { $message = new-object System.Net.Mail.MailMessage($fromAddress, $toAddress, $subject, $body) $smtpServer = "smtp.gmail.com" $client = new-object System.Net.Mail.SmtpClient($smtpServer) $client.EnableSsl = $TRUE $client.Port = 587 $client.Credentials = new-object System.Net.NetworkCredential($fromAddress, $monitorPassword) $client.Send($message) } # make a request to the site and return the status code. Return 'Failed' if anything goes wrong function CheckSiteStatus([string]$url) { $req = [System.Net.HttpWebRequest]::Create($url) try { $res = $req.GetResponse() $res.StatusCode } catch { "Failed" } } function RestartSite([string]$site) { C:\Windows\system32\inetsrv\appcmd stop site $site C:\Windows\system32\inetsrv\appcmd start site $site } function CheckSite([string]$url, [string]$site) { $status = CheckSiteStatus $url if ($status -eq "OK") { "" } else { # attempt to restart site RestartSite $site "site '$site' failed to respond`n" } } function CheckSites() { $body = "" foreach($site in $sites.Keys) { $url = $sites[$site] $body += CheckSite $url $site } if($body -ne "") { SendMessage $body $body } else { "OK" } } CheckSites
I’ve set it up with Task Scheduler to run every 10 minutes. One of the things I discovered when doing this is that if you say your task action is ‘C:\Scripts\Monitor.ps1’, you will just get notepad.exe executing You have to explicitly launch powershell and invoke: ‘powershell C:\Scripts\Monitor.ps1’.
Nice script Mike.
ReplyDeleteI've been using the web service Pingdom on for service monitoring http://www.pingdom.com/ Although I this won't try to fire the thing back up for me and you have to pay for more than one site.
This is a useful tool. I would however use Boo (or IronRuby) for such a script. It would probably be shorter and more readable.
ReplyDeleteI am going to set this up on my server soon and will post my port.
Ken,
ReplyDeleteI agree. I'm not a great fan of Powershell as a language. I think MS really missed a trick by not using IronPython in this role. However having PS on every windows machine, plus the fact that it natively talks .NET, COM and WMI makes it pretty compelling for these kinds of scripting tasks.
very nice! thanks for sharing
ReplyDeleteCheck this powershell script top monitor an application
ReplyDeleteCheck this powershell script top monitor an application
ReplyDeletehttp://itbookmarks.blogspot.ca/2013/09/monitoring-application-with-powershell.html