Collect and email Exchange Server stats automatically using PowerShell
Here’s a quick and dirty way to monitor and keep a record of some basic server statistics even when you’re not in the office. I’m sure there are many very nice tools out there that can do the same thing, but this one is free!
And who doesn’t like free?
This script gathers the following performance counters from my Exchange servers and one domain controller and then emails them to me in a nice, neat table:
- \Processor(_Total)\% Processor Time
- \LogicalDisk(C:)\Free Megabytes
- \Memory\Available Mbytes
- \MSExchangeTransport Queues(_total)\Submission Queue Length
- \MSExchangeIS\Active User Count
An array would be probably a better way to feed the server names into the GetStats function. Maybe I’ll get around to setting it up that way someday. (Update 3/21/2013: Done! Corrected script is below.) In order to get useful statistics for CPU and memory usage, the script takes just over 10 minutes per server. What I have here isn’t perfect, but it works. Feel free to recommend changes or additions in the comments.
Here’s how you use this:
- Create or select an account that has permissions to read performance counters on your target servers.
- Create a folder to store the message body. I created a folder under “C:\Temp\” called Tasks. Make sure the account that will be running this script has at least Modify permissions to this folder.
- Modify this script to suit your own environment according to the instructions (in green).
- Copy the script to “C:\Windows\System32” and create a scheduled task to run it at least once per day. I run mine twice during the highest usage periods around 9:30 and 3:30.
|# Filename: Get_ServerStats.ps1
# Author: Jay Carper (http://exchangetips.us)
# Version: 13.3.21
# Purpose: Gathers statistics on Exchange servers and emails them.
# ***Change the value of $ServerConfig as indicated: ***
# 1 – If you only have one Exchange server with all roles, change the value of
# $ServerConfig to 1.
# 2 – If you have combined the CAS and Hub roles together on any number of servers
# but keep the Mailbox role separate, change the value of $ServerConfig to 2.
# 3 – If you have CAS, Hub, and Mailbox roles running on separate servers, change
# the value of ServerConfig to 3.
# 4 – If you have some other configuration, sorry, I didn’t include it. Feel
# free to make whatever changes you require to this script.
# ***Enter the name of the global catalog server that you want to monitor***
# Replace “DomCon01” below with the name of the GC DC that your Exchange
# installation primarily relies on. There could be other servers, but this
# script will only monitor one DC. If you don’t want to monitor your GC,
# set $GlobalCatalog to $Null.
# ***Enter the required information for sending the final email***
# -Replace “Sender@domain.com” with the email address that you want the email to
# come from.
# -Replace “Recipient@domain.com” with the email address of the mailbox that will
# receive the results.
# -Replace “hub.domain.com” with the name of your smtp server.
$ServerConfig = 1
# Defines variables for each of the counters to be reported
# Loads Exchange 2010 Powershell snapin if it isn’t already loaded.
# HTML tags to open the body of the email.
# Body text, table tags, and column headers for the output.
# Gets counter statistics from the given server and outputs it in an html table.
# CPU usage. A single sample is useless, so I set it to take 10 samples, 30
# Free Disk Space
# Memory usage. See my comment about sampling CPU usage.
# Submission queues on the hub transport servers.
# Mailbox user count.
# Submission queues and mailbox user count on a combined server. Puts mailbox
# Domain Controller. I didn’t have a unique counter I wanted for the DC, so I
# HTML tag to close the table row.
# Gather hub server info and call GetStats
# Gather cas server info and call GetStats
# Gather mailbox server info and call GetStats
# Gets the server info and calls GetStats for organizations with a single Exchange
# Gets the server info and calls GetStats for organizations that combine the CAS and
# Gets the server info and calls GetStats for organizations that have separate
# If $GlobalCatalog is not $Null, calls GetStats for the GC.
# HTML tags to close the body of the email.
# Send an email to the Exchange admin with the results.
Do you know what the hardest part about writing these kinds of posts is? Getting all the HTML formatting right so the code looks correct in WordPress. It frequently removes line feeds and converts the characters I intended to display into the characters it thinks I intended to display. It’s possible WordPress has been taking cues from Microsoft on that point. I thoroughly tested this script, so I’m going to blame all mistakes on WordPress. (Just kidding! Even after testing, it’s possible that I made some mistakes of my own.) If you see anything that looks wrong, please let me know.