PowerShell: Server Down Time Monitoring system with Email and SMS Alerts using Twilio

Introduction

Quite often when we have mission-critical application running in servers, we have to ensure zero down time of the servers. However this may not be really possible always. In such a scenario one of the options is to constantly ping the server to ensure that it is up and if at all there is a downtime inform the concerned people to take the necessary action.

In this article, we will create a PowerShell-based scheduled job that pings the server to ensure that the server is up and send alerts to users about the status of the servers via email as well as SMS using Twilio API.

Implementation

As part of the implementation, we will be storing the server IPs in a text file.

 We will read each of the Server IPs, Ping them and generate an excel report. At the same time, we will send the report to business users using Email and SMS by leveraging the Twilio API. 

As the first step, in the PS file, we will create an excel object using the statement

$ResultExcel = new-object -comobject excel.application

For each server IP in the text file, we will create a row in the excel and ping the server using

$pingResult = Test-Connection $Server -Count 1 -ea silentlycontinue

Based on the success, we will update the excel row with UP/DOWN value and conditionally format it :

if($pingResult){
  
 
$ExcelWorksheet.Cells.Item($row,1) = $Server
$ExcelWorksheet.Cells.Item($row,2) = "UP"
$ExcelWorksheet.Cells.Item($row,1).Interior.ColorIndex = 17
$ExcelWorksheet.Cells.Item($row,2).Interior.ColorIndex = 4
 
$row++
}
else {
$ExcelWorksheet.Cells.Item($row,1) = $Server
$ExcelWorksheet.Cells.Item($row,2) = "DOWN"
$ExcelWorksheet.Cells.Item($row,1).Interior.ColorIndex = 17
$ExcelWorksheet.Cells.Item($row,2).Interior.ColorIndex = 3
$arrayID  = $downServerArray.Add($Server)
$row++}
 
}

For each down server, we will add it to an array using

$downServerArray.Add($Server)

At this point, we have an excel generated that contains the server ping results :

We also have the results shown in the command line as below :

Send Down Server Report as Email

To ensure that the server down time is taken care of in a timely manner, we have to mail the business users which we will be doing PowerShell command Send-MailMessage

At first, we will be creating the HTML body of the mail by iterating the downServerArray as shown below :  

$Body ='<style>body{background-color:lightgrey;}</style>'
 
 $Body = $Body + " <body> Hi Priyan, <br /><br /> The below mentioned servers are down at the moment. Please check on these servers.  <br /><br /> "
 
  $Body = $Body + " <table style='border-width: 1px;padding: 0px;border-style: solid;border-color: black;'><th style='background-color:black;color : white; font-weight:bolder;'> Server IPs </th> "
 
foreach($item in $downServerArray)
{
     Write-Host $item -ForegroundColor red -BackgroundColor white  
     $Body = $Body + " <tr style='background-color:red;color:white'><td>  $item </td></tr>"
}
 
$Body = $Body + "</table></br></br> Regards,</br>IT Team</body>"

Once we have specified the From/To and Body parameters we can send the mail using the below command :

Send-MailMessage -To "$MailtTo" -from "$MailFrom" -Subject $MailSubject -Body "$Body"  -BodyAsHtml

Full Script :

$PingResultPath = ".\PingResults.xls"
  
$ResultExcel = new-object -comobject excel.application 
  
if (Test-Path $PingResultPath) 
{ 
$ResultWorkbook = $ResultExcel.WorkBooks.Open($PingResultPath) 
$ExcelWorksheet = $ResultWorkbook.Worksheets.Item(1) 
}
  
else { 
$ResultWorkbook = $ResultExcel.Workbooks.Add() 
$ExcelWorksheet = $ResultWorkbook.Worksheets.Item(1)
}
  
$ResultExcel.Visible = $True
  
$downServerArray = [System.Collections.ArrayList]@()
  
$ExcelWorksheet.Cells.Item(1, 1) = "MachineName"
$ExcelWorksheet.Cells.Item(1, 2) = "Ping Result"
  
$Servers = gc .\ServersList.txt
$count = $Servers.count
 
$ExcelWorksheet.Cells.Item(1,1).Interior.ColorIndex = 6
$ExcelWorksheet.Cells.Item(1,2).Interior.ColorIndex = 6
 
$row=2
  
$Servers | foreach-object{
$pingResult=$null
$Server = $_
$pingResult = Test-Connection $Server -Count 1 -ea silentlycontinue
  
if($pingResult){
  
$ExcelWorksheet.Cells.Item($row,1) = $Server
$ExcelWorksheet.Cells.Item($row,2) = "UP"
$ExcelWorksheet.Cells.Item($row,1).Interior.ColorIndex = 17
$ExcelWorksheet.Cells.Item($row,2).Interior.ColorIndex = 4
  
$row++}
else {
  
$ExcelWorksheet.Cells.Item($row,1) = $Server
$ExcelWorksheet.Cells.Item($row,2) = "DOWN"
$ExcelWorksheet.Cells.Item($row,1).Interior.ColorIndex = 17
$ExcelWorksheet.Cells.Item($row,2).Interior.ColorIndex = 3
 
 $arrayID  = $downServerArray.Add($Server)
  
$row++}
}
  
# Format the excel
   
# To wrap the text           
$d = $ExcelWorksheet.UsedRange 
$null = $d.EntireColumn.AutoFit()
  
##to set column width and cell alignment
$ExcelWorksheet.Columns.Item(1).columnWidth = 24
$ExcelWorksheet.Columns.Item(2).columnWidth = 24
$ExcelWorksheet.Columns.HorizontalAlignment = -4131
$ExcelWorksheet.rows.item(1).Font.Bold = $True 
  
##to apply filter
$headerRange = $ExcelWorksheet.Range("a1","n1")
$headerRange.AutoFilter() | Out-Null
 
$xlFixedFormat = [Microsoft.Office.Interop.Excel.XlFileFormat]::xlWorkbookDefault
$enddate = (get-date -f yyyy-MM-dd).tostring()
$timeStamp= get-date -f MM-dd-yyyy_HH_mm_ss
$ResultExcel.ActiveWorkbook.SaveAs( (get-location).tostring() +"\" +$timeStamp +".xlsx", $xlFixedFormat)
 
$ResultExcel.Workbooks.Close()
$ResultExcel.Quit()
 
 
Write-Host ' Number of Servers that are down at the moment : ' $downServerArray.Count
 
if($downServerArray.Count -gt 0)
{
   $Body ='<style>body{background-color:lightgrey;}</style>' 
 $Body = $Body + " <body> Hi Priyan, <br /><br /> The below mentioned servers are down at the moment. Please check on these servers.  <br /><br /> "
  $Body = $Body + " <table style='border-width: 1px;padding: 0px;border-style: solid;border-color: black;'><th style='background-color:black;color : white; font-weight:bolder;'> Server IPs </th> "
foreach($item in $downServerArray)
{
     Write-Host $item -ForegroundColor red -BackgroundColor white   
     $Body = $Body + " <tr style='background-color:red;color:white'><td>  $item </td></tr>"
}
$Body = $Body + "</table></br></br> Regards,</br>IT Team</body>"
$PSEmailServer = 'eamail.onepb.net'
$SmtpUser = 'SathyavrathanP@domain.com'   
$smtpPassword = '<Smtp User Password>'  
$MailtTo ="SathyavrathanP@domain.com"
 
$MailFrom = 'SathyavrathanP@domain.com'   
$MailSubject = 'Server Ping Status'   
$Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList $SmtpUser, $($smtpPassword | ConvertTo-SecureString -AsPlainText -Force)   
Send-MailMessage -To "$MailtTo" -from "$MailFrom" -Subject $MailSubject -Body "$Body"  -BodyAsHtml  
write-Output " `r`n Custom Message : Server Status Email Sent to Business Users" 
}
else{
Write-Host 'All Servers are up' -ForegroundColor red -BackgroundColor white   
}

Send SMS using Twilio

You can further enhance the above PowerShell code to send the server downtime reports to Mobile as SMS using Twilio messaging system. In order to do that you will have to register for Twilio account from here. Once you have created the account, you will get an Account SID and Authentication Token which you can see here.

Now you can procure a phone number from which you will be sending the SMS by going to this link. After procurement, it will come up in the Manager Numbers section. 


Now we can make use of the PowerShell script from GitHub to send SMS as needed from the PS Script. The full code is as shown below :

<#
.Synopsis
   Robert Allen - @TheMasterPrawn 15/06/2016
   Uses the twilio SMS api to send an SMS, you need a twilio account on twilio.com
   Useful for texting someone as part of some PowerShell automation.
.EXAMPLE
.\Send-TwilioSMS.ps1 -AccountSid "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" -authToken "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
    -fromNumber "+353861111111" -toNumber "+353832222222" `
    -message "Error events made better by Twilio"
.INPUTS
   AccountSid : From API Credentials at https://www.twilio.com/console/account/settings
   authToken  : From API Credentials at https://www.twilio.com/console/account/settings
   fromNumber : Must be a valid purchased twilio number from https://www.twilio.com/console/phone-numbers/dashboard
   toNumber   : Where you want to send the message to
   message    : The message
.OUTPUTS
   Twilio will return information relating to the transaction. Might be prudent to write this to event logs.
.FUNCTIONALITY
   Uses the twilio SMS api to send an SMS
   Uses Invoke-RestMethod so dll's for service interaction are not needed
   Ensure your firewall allows you use api.twilio.com
#>
 
 
Param(
  [Parameter(Mandatory=$true)][string]$AccountSid,
  [Parameter(Mandatory=$true)][string]$authToken,
  [Parameter(Mandatory=$true)][string]$fromNumber,
  [Parameter(Mandatory=$true)][string]$toNumber,
  [Parameter(Mandatory=$true)][ValidateLength(1,160)][string]$message)
 
$secureAuthToken = ConvertTo-SecureString $authToken -AsPlainText -force
$cred = New-Object System.Management.Automation.PSCredential($AccountSid,$secureAuthToken)
 
$Body = @{
    From = $fromNumber
    To = $toNumber
    Body = $message
}
 
$apiEndpoint= "https://api.twilio.com/2010-04-01/Accounts/$AccountSid/Messages.json"
Invoke-RestMethod -Uri $apiEndpoint -Body $Body  -Credential $cred -Method "POST" -ContentType "application/x-www-form-urlencoded"

We can save this script in a PS file and invoke it from a command line by passing in the below 4 parameters :

  • AccountSid - This is the ID in the dashboard
  • Auth Token - This can be found in the dashboard along with AccountSid
  • FromNumber - This is the number you have procured for use with Twilio
  • ToNumber     - This is the destination number. Ensure that you have added this in this link

Now we can call the Send SMS REST endpoint as :

.\Send-TwilioSMS.ps1 -AccountSid "ACe673c9402ced4207d6466d9d3d1eeba1" -authToken "73510ae7c8778b2e40aea1c8043f1858" -fromNumber "+19412120521" -toNumber  "+918281671563" -message "Error events made better by Twilio"

**PowerShell Output : **

SMS Output :

Summary

Thus we saw how to implement a Server Down Time Monitoring system and alert business users Via Email and SMS system Powered by Twilio.