Monitoring Exchange 2007 / 2010 with Powershell (Part 3)

If you would like to read the other parts in this article series please go to:

Introduction

In the first part of this series we highlighted that the ability to know what is happening on your Exchange Servers quickly and accurately is key to effective Exchange Administration.

In the second part we began to construct a script that when completed could be scheduled via the Windows Task Scheduler to monitor some basic aspects of your Exchange environments – in the second part we defined the following functions:

  • Checking CPU Utilisation
  • Checking Free Memory
  • Checking Event Logs
  • Checking each server for specific Exchange Roles and executing the relevant tests

In this, the third instalment we will continue to add functionality to the script by adding the following functionality:

  • Checking the status of Exchange related Services
  • Defining a function that will perform a number of Mailbox Role tests
  • Disk SpaceTests
  • Database BackupTests

Checking Exchange Services

The check_Services function is designed to connect to the WMI namespace using the Win32_Service class and queries the State (e.g. Running, Stopped) and the StartMode (e.g. Automatic, Manual) of a Service which has the word “Exchange” within its name.

As different Exchange server roles can have different combinations of services – it makes sense to perform the wildcard – like on the service name to see if “Exchange” contained within it.

Additionally the logic behind the getting the Service Status and StartMode is that you can normally assume that if the service is “Stopped” and its StartMode is “Automatic” then something is probably wrong.

The check_Services function is called from the checkRoles() function (which was defined in the previous part of this series). check_Services accepts one parameter which is the name of the Exchange server that it will query the WMI namespace of (this is taken from the ExchangeServers.txt).

The query to the WMI class is very prescriptive as we are looking for Service Names which contain Exchange ($_.Name -like '*Exchange*') where their State is not equal to “Running” (-and $_.State -ne 'Running') and the Start Mode is set to “Auto” (-and -and $_.StartMode -eq 'Auto').

The function then places all of the services which conform to the above criteria in a variable called $ExchangeServicesFound.

Then using a foreach loop the function cycles through the information in the $ExchangeServicesFound variable and generates a message body which details the services which are not started and we then send that information to the administrator using the SMTPAlertMessage function.

function check_Services($strServer){

$ExchangeServicesFound = Get-WmiObject Win32_Service -ComputerName $strServer | where {$_.Name -like '*Exchange*' -and $_.State -ne 'Running' -and $_.StartMode -eq 'Auto'}

$MessBody = "<p>The following Exchange Services which are set to run Automatically are currently stopped on: $strServer</p>"

foreach($svc in $ExchangeServicesFound){

$MessBody = $MessBody + "<p>" + $svc.Name + "</p>"

}

SMTPAlertMessage "Exchange Services Error" $MessBody

}

Performing Mailbox Roles Test

As the name suggests the mailBoxRoleTests function (called from checkRoles()) performs a number of tests against the mailbox server which is passed from the ExchangeServers.txt file.

The function itself performs the following tasks:

  • Checks the physical size of both the Mailbox and Public Folders databases and compares them against threshold values which you can set in $DBSizeThreshold and $PDBSizeThreshold
  • Checks to ensure that Mailbox and Public Folder databases are mounted
  • Checks the most recent backup information (this is performed by calling a specific function called checkExchangeDatabaseBackups which is detailed later on)
  • Checks the overall free disk space on each Exchange Server against the  $DiskspacePercentageFree threshold percentage (again this is called from a separate function)

As this is quite a large function, rather than go into specific details I will cover some of the highlights.

mailBoxRoleTests initially will check the if all of the Mailbox Databases and Public Folder databases are mounted on the server in question – this is accomplished via the Get-MailboxDatabase and Get-PublicFolderDatabase CMDlets using the -Status switch (the status is not retrieved automatically when just using the basic command).

If any registered databases are found to be dismounted – the script will send an e-mail alert to the administrator.

The function will then move onto evaluate the physical size of each Mailbox Database and compare that with the threshold values which are defined for Mailbox and PF databases at the start of the script (this is accomplished via using the Get-ChildItem cmdlet to retrieve the properties of the physical EDB path – which includes the file size (length)).

The function then finishes off by calling the checkExchangeDatabaseBackups and checkDiskSpaceFree functions (which are defined next).

function mailBoxRoleTests($strMBXServer){

$MDB = Get-MailboxDatabase -Server $strMBXServer -Status

$PFD = Get-PublicFolderDatabase -Server $strMBXServer -Status

Write-Host "Checking Mailbox Databases" -ForegroundColor Cyan

foreach($MxDB in $MDB){

if($MxDB.Mounted -eq $False){

$MessBody = "<b>Exchange Server Mailbox Database $MxDB is not Mounted</b>"

SMTPAlertMessage "Exchange Database not Mounted" $MessBody

}

}

Write-Host "Checking Public Folders Databases" -ForegroundColor Cyan

foreach($pfDB in $PFD){

if($pfDB.Mounted -eq $False){

$MessBody = "<b>Exchange Server Public Folder Database $pfDB is not Mounted</b>"

SMTPAlertMessage "Exchange Public Folder Database not Mounted" $MessBody

}

}

# Get the Physical Database Size

Write-Host "Checking Mailbox Database Size" -ForegroundColor Cyan

foreach($MvxDBS in $MDB){

$dbSize = Get-ChildItem $MvxDBS.EdbFilePath

$sizeObject = New-Object PSObject

$sizeObject | Add-Member NoteProperty -Name "Size (MB)" -Value ("{0:n0}" -f ($dbSize.Length/1024KB))

if($dbSize.Length/1024KB -gt $DBSizeThreshold){

$MessBody = "<b>Exchange Server Mailbox Database $MvxDBS is over sized at: $sizeObject</b>"

SMTPAlertMessage "Exchange Database is over threshold size" $MessBody

}

}

Write-Host "Checking Public Folder Database Size" -ForegroundColor Cyan

foreach($pvxDBS in $PFD){

$dbSize = Get-ChildItem $pvxDBS.EdbFilePath

$sizeObject = New-Object PSObject

$sizeObject | Add-Member NoteProperty -Name "Size (MB)" -Value ("{0:n0}" -f ($dbSize.Length/1024KB))

if($dbSize.Length/1024KB -gt $PDBSizeThreshold){

$MessBody = "<b>Exchange Server Public Folder Database $pMvxDBS is over sized at: $sizeObject</b>"

SMTPAlertMessage "Exchange Public Folder Database is over threshold size" $MessBody

}

}

Write-Host "Checking Backup Information" -ForegroundColor Cyan

# Get backup information

checkExchangeDatabaseBackups $strMBXServer

# Get disk information

Write-Host "Checking Free Disk Space" -ForegroundColor Cyan

checkDiskSpaceFree $strMBXServer

}

Checking Physical Disk Space

The purpose of the checkDiskSpaceFree function is, as you might expect to compare the amount of free disk space on the provided Exchange server to the threshold value which is contained within $DiskspacePercentageFree.

If the actual percentage of disk space free is lower than the threshold value – and e-mail is sent to the administrator.

Using the WMI class Win32_LogicalDisk all disks on the given server which are of DriveType = 3 (Local Disk) are retrieved and have their free space calculated.

function checkDiskSpaceFree($strServer){

$fixedDisks = Get-WmiObject -ComputerName $strServer -Class Win32_LogicalDisk -Filter "DriveType = 3"

foreach($disk in $fixedDisks){

$id = $disk.DeviceID

[float]$size = $disk.size

[float]$free = $disk.FreeSpace

$pctFree = [Math]::Round(($free / $size) * 100, 2)

$szGB = [Math]::Round($size / 1073741824, 2)

$frGB = [Math]::Round($free / 1073741824, 2)

if($pctFree -lt $DiskspacePercentageFree){

$MessBody = "<p>Exchange Server Disk Space Issue: $strServer disk $id has less than $DiskspacePercentageFree% Free</p><p>Disk Size: $szGB</p><p>Free Space: $frGB</p>"

SMTPAlertMessage "Exchange Disk Issue Detected" $MessBody

}

}

}

Checking Exchange Backups

The checkExchangeDatabaseBackups function performs the following tasks:

  • Checks each Mailbox database to see if there has ever been a backup
  • Checks the last backup time (either Full, Incremental or Differential) against the threshold value contained within the $lastBackupThreshhold constant – if the time since the last is greater than the threshold value then a notification is sent to the administrator.

The function itself get the backup information into a variable called $Svrs using the Get-MailboxDatabase cmdlet with the –Status Switch (which populates the backup information) – then by using some of PowerShell’s time and date CMDlets (New-TimeSpan span and Get-Date) it determines the amount of days since the last backup.

function checkExchangeDatabaseBackups($strMailboxServer){

# These can be set to $True if you use them

$CheckIncs = $false

$CheckDiffs = $false

$Svrs = Get-MailboxDatabase -Server $strMailboxServer -Status

foreach($svr in $Svrs){

if($svr.LastFullbackup -eq $null -and $svr.LastIncrementalBackup -eq $null -and $svr.LastDifferentialBackup -eq $null -and $svr.Mounted -eq $true){

$MessBody = "<b>Exchange Server Mailbox Database: $SVR has NEVER been backed up</b>"

SMTPAlertMessage "Exchange Database Backup issue" $MessBody

}else{

if($svr.LastFullBackup -ne $null){

$elapsedTime = New-TimeSpan $($svr.LastFullBackup) $(Get-Date)

if($elapsedTime.days -gt $lastBackupThreshhold){

$MessBody = "<b>Exchange Server Mailbox Database: $SVR was last backed up $elapsedTime.days ago</b>"

SMTPAlertMessage "Exchange Database Backup issue" $MessBody

}

}

if($svr.LastIncrementalBackup -ne $null){

if($CheckIncs -eq $true){

$elapsedTime = New-TimeSpan $($svr.LastIncrementalBackup) $(Get-Date)

if($elapsedTime.days -gt $lastBackupThreshhold){

$MessBody = "<b>Exchange Server Mailbox Database: $SVR last Incremental backup was $elapsedTime.days ago</b>"

SMTPAlertMessage "Exchange Database Backup issue" $MessBody

}

}

}else{

$MessBody = "<b>Exchange Server Mailbox Database: $SVR No Incremental backup information found</b>"

SMTPAlertMessage "Exchange Database Backup Information" $MessBody

}

if($svr.LastDifferentialBackup -ne $null){

if($CheckDiffs -eq $true){

$elapsedTime = New-TimeSpan $($svr.LastDifferentialBackup) $(Get-Date)

if($elapsedTime.days -gt $lastBackupThreshhold){

$MessBody = "<b>Exchange Server Mailbox Database: $SVR last Differential backup was $elapsedTime.days ago</b>"

SMTPAlertMessage "Exchange Database Backup issue" $MessBody

}

}

}else{

$MessBody = "<b>Exchange Server Mailbox Database: $SVR No Differential backup information found</b>"

SMTPAlertMessage "Exchange Database Backup Information" $MessBody

}

}

}

}

Summary

This wraps up part three of this series. In this part we have covered how you can check Exchange Related Services on each Exchange role, perform a number of health tests against the Mailbox Server role, check the physical disk space on your Mailbox Servers and check when the last backups were last performed.

In the next and final part we will define health checking functions for the CAS and HT roles, put the whole script together, explain how you can schedule the script and make a few suggestions on how the script can be developed further.

If you would like to read the other parts in this article series please go to:

Andy Grogan

Share
Published by
Andy Grogan

Recent Posts

Apple Event 2019: Everything you need to know about the new iPhone 11

Apple has just unveiled three new iPhones — iPhone 11, iPhone 11 Pro, and iPhone Pro Max. Here is everything…

13 hours ago

Review: CoreView CoreAdmin for Microsoft Office 365

CoreView simplifies the challenging management of Microsoft Office 365 by creating its own management interface. Here’s our review.

16 hours ago

Exchange 2019: Should you update now or wait a little longer?

Exchange 2019 is out there glittering like a shiny new toy. But should you take the plunge and update now?…

19 hours ago

Privacy-by-design principles: Getting it right from the start

Embedding privacy-by-design principles in the building and design of a business, website, application, product, or tool is a good thing…

1 day ago

Check mailbox auditing status in Exchange Online with PowerShell

Office 365 Exchange Online admins must ensure all mailboxes created in Office 365 have auditing enabled. Here’s how to check…

2 days ago

T-Suite Podcast: Creative destruction — Proper IT asset liquidation

If you plan to liquidate your IT assets, it is critical you have a chain of custody for every device…

2 days ago