Exchange 2010 Monitoring Script

There is a new script: Exchange 2010 Monitoring
I wrote this script to check if everything on Exchange is working properly.

This script will monitor Exchange 2010 in a DAG environment.
Following Monitors are included:
  • ExchangeQueue
  • MailboxDatabaseCopy
  • MailboxDatabaseContentIndex
  • ServerDiskFreeSpace
  • ExchangePrivatDatabaseBackup
  • ExchangePublicDatabaseBackup
There are to modes:

Mode 1: Monitoring Exchange without Backup check

Checks Exchange and sends E-Mail if Treshhold is reached to Exchange Admin

Mode 2: Monitoring Exchange Backup only

Checks Exchange-Backup and sends E-Mail to Backup Admin

##############################################################################
<# 
.SYNOPSIS 
       Exchange 2010 Monitoring Script.

.DESCRIPTION 
    This script will monitor Exchange 2010 in a DAG environment.
    following Monitors are included:
     * ExchangeQueue
     * MailboxDatabaseCopy
     * MailboxDatabaseContentIndex
     * ServerDiskFreeSpace
     * ExchangePrivatDatabaseBackup
     * ExchangePublicDatabaseBackup
                             
    You will get an email information if an error occured


.NOTES 
    Version                 : 1.2 public
    Rights Required         : Local admin on Exchange Server
    Sched Task Req'd        : No, but makes sense
    Exchange Version        : Exchange 2010 tested, Exchange 2007 probably
    Author                  : Manfred Peer, Exchange System Engineer
    Email/Blog              : maeffy@gmail.com http://peerfect.blogspot.com
    Disclaimee              : You running this script means you won't blame me if this breaks your stuff.
                            : Use at your own risk!
    Modification V1.1       : Checks Primary ActiveManager in DAG to run on one DAG Member only
    Fix V1.2                : Problem with ServerDiskFreeSpace solved

.LINK 
    http://peerfect.blogspot.com

.PARAMETER Backupcheckonly
    Specifies the Check mode. Checks Backup status only. Default check is without Backupcheck.

.PARAMETER BackupAdmin
    Sends additional mail to BackupAdmin

.EXAMPLE
    .\Exchange_Monitoring_Script.ps1
   
    Checks Exchange and sends E-Mail if Treshhold is reached to Exchange Admin

.EXAMPLE
    .\Exchange_Monitoring_Script.ps1 -Backupcheckonly -BackupAdmin
   
    Checks Exchange-Backup and sends E-Mail to Backup Admin

.INPUTS
    None. You cannot pipe objects to this script.
#>
#Requires -Version 2.0

#Connect-ExchangeServer -auto

#region Parameters
[CmdletBinding()]
param(
    [parameter(ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, Mandatory=$false)][ValidateNotNullOrEmpty()]
    [switch] $Backupcheckonly = $false,
    [parameter(ValueFromPipeline=$false, ValueFromPipelineByPropertyName=$false, Mandatory=$false,HelpMessage="BackupAdmin Email Address:")][ValidateNotNullOrEmpty()]
    [string] $BackupAdmin
)

$Script:Servername = $env:computername
$Script:MailServer = "Your Mail Server"
$Script:BodyMessage = @()
$Script:MailAttachments = @()
$Script:MailAddresses = @()
$Script:MailFromAddress = "exchange.monitoring@domain.com"
$Script:MailToAddress = "exchange.monitoring@domain.com"
$Script:MailToAddress1 = "additional.user@domain.com"
$Script:AlarmSubject = "Exchange 2010 Monitoring Script"
$Script:AlarmBody = "`n`n" + "Please see attached log file for more information (if any)"
$Script:Exchange_Queue_Log = "c:\temp\exchange_queue.txt"
$Script:Exchange_MailboxDatabaseCopy_Log = "c:\temp\Exchange_MailboxDatabaseCopy_LOG.txt"
$Script:Exchange_MailboxDatabaseContentIndex_Log = "c:\temp\Exchange_MailboxDatabaseContentIndex_Log.txt"
$Script:Exchange_ServerDiskFreeSpace_Log = "c:\temp\Exchange_ServerDiskFreeSpace_Log.txt"
$Script:ExchangeQueueTreshHold = "10"       # More then 10 E-Mails in Queue
$Script:ServerDiskFreeSpaceTreshHold = "10" # Lower or equal 10% of any Disk
$Script:DatabaseBackupTreshHold = "1" # Days back to check
$Script:Triggeralarm = $false
$Script:PrimaryActiveManager = $false

function Init
{
   #Checks if Server is PrimaryActiveManager. Should run on one Host in DAG only
   if ((Get-DatabaseAvailabilityGroup -Status).PrimaryActiveManager -ne $env:Computername) {$PrimaryActiveManager = $true}
    $Script:MailAddresses += $MailToAddress
    if ($MailToAddress1) {$Script:MailAddresses += $MailToAddress1}
    if ($Backupcheckonly -and $BackupAdmin) {$Script:MailAddresses += $BackupAdmin}
    if (Test-Path $Exchange_Queue_Log) {Remove-Item $Exchange_Queue_Log -Force | Out-Null}
    if (Test-Path $Exchange_MailboxDatabaseCopy_Log) {Remove-Item $Exchange_MailboxDatabaseCopy_Log -Force | Out-Null}
    if (Test-Path $Exchange_MailboxDatabaseContentIndex_Log) {Remove-Item $Exchange_MailboxDatabaseContentIndex_Log -Force | Out-Null}
    if (Test-Path $Exchange_ServerDiskFreeSpace_Log) {Remove-Item $Exchange_ServerDiskFreeSpace_Log -Force | Out-Null}
}

function Send_AlarmMessage
{
    $smtp = New-Object Net.Mail.SmtpClient($MailServer)
    $msg = New-Object Net.Mail.MailMessage
    $msg.From = $MailFromAddress
    foreach ($Recipient in $MailAddresses) {$msg.To.Add($Recipient)}
    $msg.Subject = $AlarmSubject
    foreach ($Message in $BodyMessage){$msg.Body += $Message}
    $msg.Body += $AlarmBody
    foreach ($AttachFile in $MailAttachments){$att = New-Object Net.Mail.Attachment($AttachFile);$msg.Attachments.Add($att)}
    $smtp.Send($msg)
    $msg.finalize
    $msg.dispose()
    $smtp.finalize
}

function Check_ExchangeQueue
{
    while ($PrimaryActiveManager) {
       #http://gallery.technet.microsoft.com/scriptcenter/e0bb250e-e699-4c6c-a5be-f1af245a2219
       if ($ExchangeQueue = Get-ExchangeServer | where { $_.isHubTransportServer -eq $true } | get-queue | Where-Object { $_.MessageCount -gt $ExchangeQueueTreshHold })
       {
           $ExchangeQueue | Format-Table -Wrap -AutoSize | Out-File -filepath $Exchange_Queue_Log
           $Script:BodyMessage += "`n" + "EXCHANGE SERVER QUEUE ($Script:ExchangeQueueTreshHold Messages) THRESHOLD REACHED - PLEASE CHECK EXCHANGE QUEUES"
           #$BodyMessage += "`n`n" + "Please see attached log file for more information"
           $Script:MailAttachments += $Exchange_Queue_Log
           $Script:Triggeralarm = $true
           Write-Host "Exchange 2010 Queue is not good" -ForegroundColor Red
       }
       else {Write-Host "Exchange 2010 Queue is good" -ForegroundColor Green}
   }
}

function Check_MailboxDatabaseCopy
{
    while ($PrimaryActiveManager) {
       #if ($Exchange_MailboxDatabaseCopy = Get-mailboxdatabase | Get-MailboxDatabaseCopyStatus | where {$_.Status -ne "Healthy" -and $_.Status -ne "Mounted"})
       if ($Exchange_MailboxDatabaseCopy = Get-MailboxDatabaseCopyStatus | where {$_.Status -ne "Healthy" -and $_.Status -ne "Mounted"})
       {
           $Exchange_MailboxDatabaseCopy | select Name,DatabaseName,Status,MailboxServer,ActiveDatabaseCopy,ActivationSuspended | Format-Table -Wrap -AutoSize | Out-File -filepath $Exchange_MailboxDatabaseCopy_Log
           $Script:BodyMessage += "`n" + "EXCHANGE SERVER DATABASE COPY ERROR - PLEASE CHECK EXCHANGE DATABASES" + "`n"
           $Script:MailAttachments += $Exchange_MailboxDatabaseCopy_Log
           $Script:Triggeralarm = $true
           Write-Host "Exchange 2010 MailboxDatabaseCopy is not good" -ForegroundColor Red
       }
       else {Write-Host "Exchange 2010 MailboxDatabaseCopy is good" -ForegroundColor Green}
   }
}

function Check_MailboxDatabaseContentIndex
{
    while ($PrimaryActiveManager) {
       #if ($Exchange_MailboxDatabaseContentIndex = Get-mailboxdatabase | Get-MailboxDatabaseCopyStatus | where {$_.contentindexstate -ne "Healthy"})
       if ($Exchange_MailboxDatabaseContentIndex = Get-MailboxDatabaseCopyStatus | where {$_.contentindexstate -ne "Healthy"})
       {
           $Exchange_MailboxDatabaseContentIndex | select Name,DatabaseName,Status,ContentIndexState,MailboxServer,ActiveDatabaseCopy,ActivationSuspended | Format-Table -Wrap -AutoSize | Out-File -filepath $Exchange_MailboxDatabaseContentIndex_Log
           $Script:BodyMessage += "`n" + "EXCHANGE SERVER DATABASE INDEX ERROR - PLEASE CHECK EXCHANGE DATABASES INDEX" + "`n"
           $Script:MailAttachments += $Exchange_MailboxDatabaseContentIndex_Log
           $Script:Triggeralarm = $true
           Write-Host "Exchange 2010 MailboxDatabaseIndex is not good" -ForegroundColor Red
       }
       else {Write-Host "Exchange 2010 MailboxDatabaseIndex is good" -ForegroundColor Green}
   }
}

function Check_ServerDiskFreeSpace
{
    if ($Exchange_ServerDiskFreeSpace = `
        Get-WmiObject -query "select name,driveletter,capacity,freespace from win32_volume where drivetype=3" | Select Name,Driveletter, `
        @{label="SizeGB"; Expression={($_.capacity / 1GB).tostring("F0")}}, `
        @{label="FreeGB"; Expression={($_.freespace / 1GB).tostring("F0")}}, `
        @{label="PercentFree"; Expression={($_.freespace*100/$_.capacity).tostring("F0")}} | `
        Where {[int]$_.PercentFree -le [int]$Serverdiskfreespacetreshhold -and $_.PercentFree -ne "100"} | Sort-Object -Property PercentFree | ft -autosize )
    {
        $Exchange_ServerDiskFreeSpace | Format-Table -Wrap -AutoSize | Out-File -filepath $Exchange_ServerDiskFreeSpace_Log
        $Script:BodyMessage += "`n" + "EXCHANGE SERVER DISK SPACE PROBLEM on $Servername - PLEASE CHECK EXCHANGE DISKSPACE"  + "`n"
        $Script:MailAttachments += $Exchange_ServerDiskFreeSpace_Log
        $Script:Triggeralarm = $true
        Write-Host "Exchange 2010 Server Disk Percent Free is not good" -ForegroundColor Red
    }
    else {Write-Host "Exchange 2010 Server Disk Percent Free is good" -ForegroundColor Green}
}

function Check_ExchangePrivatDatabaseBackup
{
    while ($PrimaryActiveManager) {
       $Exchange_DataBaseBackup = Get-MailboxDatabase -Status -Server $Servername
       foreach($Database in $Exchange_DataBaseBackup)
        {
           $ExchangeDBname = $Database.name
           $ExchangeServername = $Database.servername    
           $LastBackup = $Database.LastFullBackup; $CurrentDate = Get-Date
           if ($LastBackup -eq $null)
           {    
               $Script:Triggeralarm = $true
               $Script:BodyMessage += "`n" + "EXCHANGE SERVER PRIVAT DB BACKUP PROBLEM (not run) on $Servername - PLEASE CHECK EXCHANGE BACKUP"  + "`n"
               $Script:BodyMessage += "Database: $ExchangeDBname"  + "`n"
               $Script:BodyMessage += "Last Backup: $LastBackup" + "`n"
               Write-Host "Exchange 2010 Privat Backup is not good" -ForegroundColor Red
           }
           elseif (($CurrentDate - $LastBackup).days -ge $DatabaseBackupTreshHold)
           {
               $Script:Triggeralarm = $true
               $Script:BodyMessage += "`n" + "EXCHANGE SERVER PRIVAT DB BACKUP PROBLEM on $Servername - PLEASE CHECK EXCHANGE BACKUP"  + "`n"
               $Script:BodyMessage += "Database: $ExchangeDBname"  + "`n"
               $Script:BodyMessage += "Last Backup: $LastBackup" + "`n" + "Current Date: $CurrentDate" + "`n" + "Treshhold older: $Script:DatabaseBackupTreshHold Days" +"`n"
               Write-Host "Exchange 2010 Privat Backup is not good" -ForegroundColor Red
           }
           else {Write-Host "Exchange 2010 Privat Backup is good" -ForegroundColor Green}
       }
   }
}

function Check_ExchangePublicDatabaseBackup
{
    while ($PrimaryActiveManager) {
       $Exchange_DataBaseBackup = Get-PublicFolderDatabase -Status
       foreach($Database in $Exchange_DataBaseBackup)
        {
           $ExchangeDBname = $Database.name
           $ExchangeServername = $Database.servername    
           $LastBackup = $Database.LastFullBackup; $CurrentDate = Get-Date
           if ($LastBackup -eq $null)
           {    
               $Script:Triggeralarm = $true
               $Script:BodyMessage += "`n" + "EXCHANGE SERVER PUBLIC DB BACKUP PROBLEM (not run) on $Servername - PLEASE CHECK EXCHANGE BACKUP"  + "`n"
               $Script:BodyMessage += "Database: $ExchangeDBname"  + "`n"
               $Script:BodyMessage += "Last Backup: $LastBackup" + "`n"
               Write-Host "Exchange 2010 Public Backup is not good" -ForegroundColor Red
           }
           elseif (($CurrentDate - $LastBackup).days -ge $DatabaseBackupTreshHold)
           {
               $Script:Triggeralarm = $true
               $Script:BodyMessage += "`n" + "EXCHANGE SERVER Public DB BACKUP PROBLEM on $Servername - PLEASE CHECK EXCHANGE BACKUP"  + "`n"
               $Script:BodyMessage += "Database: $ExchangeDBname" + "`n"
               $Script:BodyMessage += "Last Backup: $LastBackup" + "`n" + "Current Date: $CurrentDate" + "`n" + "Treshhold older: $Script:DatabaseBackupTreshHold Days" +"`n"
               Write-Host "Exchange 2010 Public Backup is not good" -ForegroundColor Red
           }
           else {Write-Host "Exchange 2010 Public Backup is good" -ForegroundColor Green}
       }
   }
}

Init
if ($Backupcheckonly) {Check_ExchangePrivatDatabaseBackup;Check_ExchangePublicDatabaseBackup}
else
{
    Check_ExchangeQueue
    Check_MailboxDatabaseCopy
    Check_MailboxDatabaseContentIndex
    Check_ServerDiskFreeSpace
}
if ($Triggeralarm -eq $true) {Send_AlarmMessage}

##############################################################################
Have Fun!
Maeffy

Comments

Popular posts from this blog

Exchange 2007 / Exchange 2010: Daily or Hourly Messagestatistc and Warning

Out of Office Admin Tool

Re-Blog Exchange 2007 Powershell remoting solution