Saturday, November 26, 2016

Exchange 2013/2016 Cleaning up old Diagnostic and IIS Log Files

A while back I cross-posted an article by Jason Sherry on cleaning up Exchange 2013 Log files with a one-liner.
Jason's solution worked very well, until I stood up a new Exchange 2016 environment, and it just wouldn't run - no errors, it just didn't do anything.
So, I came up with a scheduled task that works awesome, and keeps those pesky logs file down to a manageable size.

A little back story:
Exchange 2013/2016 keeps pretty much every diagnostic log in order for MS Support to easily go back and find problems without having to wait for Exchange admins to manually pull logs. The problem is: Exchange does a very poor job of cleaning up said logs and they fill up your system volume very quickly.

I know, I know, disks are cheap - well businesses are cheap too, and won't always pay for what you need!

Creating the "Clean Logs" Scheduled Task:

The following task will clean up the Exchange Daily Performance Logs and IIS logs keeping only the past 3 days.

Create a Service Account:

First, you'll want to create a Service Account in your domain, which will be used to run the scheduled task. It's best practice to use service accounts rather than your own account to run scheduled tasks, so if you ever leave your position and they deactivate your account, it won't break the task!

In your domain, create a new user called something like exchscriptrunner and set a super-strong password.
The only membership it needs is Domain User, so it should be good to go.

Next, add the newly created user to the Local Administrators Group on each Exchange server. The scheduled task will need local admin rights to run PowerShell things, and since you have a super strong password, it's not an issue.

Create the scheduled task on the first Exchange server:
On one of the Exchange servers in the Task Scheduler Control Panel, click Action > Create Task...

On the General tab:

Give it a name like Clean Logs

Click "Change User or Group..." hit "Locations" and switch to your domain, then search for your exchscriptrunner service account.

Check the box for "Run with highest privileges"

On the Triggers Tab:

Click "New..."
Set it for how often you need it to clean up the logs. I run mine Daily at 10AM - no specific reason, but you do want it to run Daily. You can run It during production hours as it doesn't use many resources.


On the Actions Tab:

Set the "Action" dropdown to "Start a program"

Under Program/Script, copy/paste the following:


In the "Add arguments" field, copy/paste the following:

-NonInteractive -WindowStyle Hidden -command ". 'C:\Program Files\Microsoft\Exchange Server\V15\bin\RemoteExchange.ps1'; Connect-ExchangeServer -auto; Get-ChildItem 'C:\Program Files\Microsoft\Exchange Server\V15\Logging','C:\Inetpub\Logs' -Directory | Get-ChildItem -Include '*.log','*.blg' -Recurse | ? LastWriteTime -lt (Get-Date).AddDays(-3) | Remove-Item -ErrorAction silentlycontinue

**Note** This assumes that you have installed Exchange to the default location. If you have installed it to another location, change the "C:\Program Files\Microsoft\Exchange Server\V15\bin\RemoteExchange.ps1" and "C:\Program Files\Microsoft\Exchange Server\V15\Logging','C:\Inetpub\Logs" to match your environment.

**Note** This keeps the last 3 days of logs, which should be sufficient for any error intel gathering...if 3 days have gone by and you haven't noticed problems in Exchange, you might need some monitoring :)
To change it to more or less than 3 days, set the "AddDays(-3)" to a different number value.


In the Settings Tab:

Checkmark the following boxes:

- Allow task to be run on demand

- Stop the task if it runs longer than: 1 hour (if it runs longer than an hour, you got something wrong!)

- If the running task does not end when requested, force it to stop


Click OK when you have everything set.

Testing the Clean Logs Task:

In the main task window, right-click your new "Clean Logs" task, and click Run.

When it finishes running, you should have a (0x1) Last Run Result.

You can also go check C:\Program Files\Microsoft\Exchange Server\V15\Logging\Diagnostics\DailyPerformanceLogs (or wherever you've installed Exchange) and you should see only three days' worth of log files.

Create the scheduled task on the other Exchange servers:

Once you've successfully run the task, you'll need to create it on your other Exchange servers...this is super easy!

In the main Task Scheduler window, right-click your "Clean logs" task and click "Export" and save the file to your preferred location.

This will create an .xml file with all the settings intact.

Copy the Clean logs.xml file to each of your other Exchange servers. 

On each Exchange server, open the Task Scheduler.

Click the Task Scheduler Library folder in the left pane.

Click Action, and "Import Task..."

Select your Clean logs.xml file and hit Ok.

Now you'll see the Clean logs task at the ready state in the Task Library on each server.


To supplement the scheduled task, if you have rather small Exchange install volumes, I also like to compress the C:\Program Files\Microsoft\Exchange Server\V15\Logging directory - with zero adverse effects. To do that,
follow my post here.

Now, with this scheduled task and a compressed logging directory, you should save tons of space on your servers, and be free from filling up the drive causing mailflow to fail ;)


  1. this script simply does not work. it misses another recurse option.

    1. Have you tried running the cmdlet in PowerShell (not in a scheduled task)?
      I have it successfully running in multiple Exchange environments.

      Also, why would you want more than one "recurse" it already recursively(repetitively) looks through the Logging and Inetpub directories.

  2. I got this script working on two of my Exchange servers, but the rest of them ran successfully with (0x1) result, but no logs were being purged. All servers are sitting in the same OU, and have the same permissions. Any advise would be greatly appreciated.

    1. In the Event Logs under Application and Service Logs > Windows PowerShell, do you see a few Event 600's at the time you specified for the task to run?

      And under Application and Service Logs > Microsoft > Windows > TaskScheduler, you should see Events 129, 100, 200, 201, 102

      All else fails, I'd run this cmdlet in PowerShell by itself, and see if it completes:

      "Get-ChildItem 'C:\Program Files\Microsoft\Exchange Server\V15\Logging','C:\Inetpub\Logs' -Directory | Get-ChildItem -Include '*.log','*.blg' -Recurse | ? LastWriteTime -lt (Get-Date).AddDays(-3) | Remove-Item "

      Lemme know whatcha find!

  3. This comment has been removed by the author.

  4. tested this script, also have 0x1 and events in logfiles.
    when testing in powershell command line, i guess that there is a missing quote for the command after 'Remove-Item'.

    Will test in next shedule with:

    -NonInteractive -WindowStyle Hidden -command ". 'C:\Program Files\Microsoft\Exchange Server\V15\bin\RemoteExchange.ps1'; Connect-ExchangeServer -auto; Get-ChildItem 'C:\Program Files\Microsoft\Exchange Server\V15\Logging','C:\Inetpub\Logs' -Directory | Get-ChildItem -Include '*.log','*.blg' -Recurse | ? LastWriteTime -lt (Get-Date).AddDays(-4) | Remove-Item" -ErrorAction silentlycontinue

    i hope that this will do the trick, command looks just what i need.