Using PowerShell to delete IIS log files

It’s that time of the month again.

No, not that time. I’m talking about the «Damn! IIS log files are filling up the server again». That time of the month. All sysadmins have been there at some time or another. You’re responsible for some webserver with a fair amount of traffic, and you regularly need to delete the old log files to free up disk space. Finally you decide to try and automate the process, but how to do it? You could use any number of methods to get the job done, I am of course going to focus on using PowerShell.

Note that the following will not work with older versions of IIS than 7.5 (that means earlier than Server 2008 R2)

Where are my log files?

Finding these log files is the first step of our script. The location of IIS log files may vary from site to site. By default they are all placed in several folders in «%SystemDrive%\inetpub\logs\LogFiles».

I was keen to solve this problem for multiple servers and would rather not have to specify the directory of the log files, only the name of the website. The PowerShell code requires a bit of tasty regex to ensure the flexibility we’re after.

Import-Module WebAdministration

$Website = Get-Item IIS:\Sites\$WebsiteName
 $LogFileDirectory = $Website.logfile.directory

if ($LogFileDirectory -match "(%.*%)\\") {
 $LogFileDirectory = $LogFileDirectory -replace "%(.*%)\\","$(cmd /C echo $matches[0])"
 }

Ok, ok! So regex can be a little confusing, what the heck is going on here?

The log file directory is often specified using environment variables such as %SystemDrive%. PowerShell doesn’t understand environment varibles in the old cmd format and therefore we have to translate them using cmd.

In order to get this done automatically without user interaction, the regex will check to see if the log path starts with an environment variable and if so, run echo in cmd and pass the output back to PowerShell. Thereby ensuring paths beginning with %SystemDrive% or %windir% or whatever will not cause our script to fail.

Delete, Delete, Delete!

With our log folder located, it’s time to get our hands dirty. What’s next? Right. Delete those damn log files!

The obvious issue here is making sure we actually only delete the files we want to. We really don’t want to be in the situation of explaining that the reason the website is returning 404 errors is because we deleted the inetpub folder. The code to get the job done is a piece of cake:


$toBeDeleted = Get-ChildItem -Path $LogFileDirectory -Recurse | where {
 $_.LastWriteTime -lt (Get-Date).adddays(-$DaysToRetain) -and $_.PSIsContainer -eq $false
 }

if ($toBeDeleted -ne $null) {
 $ToBeDeleted | % {
 Remove-Item $_.FullName
 }
 }

I don’t feel the need to explain this code in detail – List all files, delete all files. Simples.

Script Parameters

I’ve only added two parameters for this script.

Let’s start off by defining which website we would like to target. Keep in mind that websites often (and by default) share the same log files folder and therefore you may be deleting logs for several sites even though you specify a website. If this is an issue you will need to define separate log file locations for each site before running this script.

How many days of retention do we want? I’m going to default this to 30 days but add the parameter for flexibility. Because of the default value, I’m not even bothering setting this to mandatory.

Putting it all together in code

TL;DR? Here is all the code sewn together in perfect harmony. Perfect harmony does of course mean that you should run this on a test environment before deploying it but you knew that already didn’t you?

Function Clean-IISLogs {
 Param(
 [Parameter(Mandatory=$true)]
 [String]$WebsiteName,

[Parameter(Mandatory=$false)]
 [Int]$DaysToRetain = 30
 )

Import-Module WebAdministration

$Website = Get-Item IIS:\Sites\$WebsiteName
 $LogFileDirectory = $Website.logfile.directory

if ($LogFileDirectory -match "(%.*%)\\") {
 $LogFileDirectory = $LogFileDirectory -replace "%(.*%)\\","$(cmd /C echo $matches[0])"
 }

$toBeDeleted = Get-ChildItem -Path $LogFileDirectory -Recurse | where {
 $_.LastWriteTime -lt (Get-Date).adddays(-$DaysToRetain) -and $_.PSIsContainer -eq $false
 }


if ($toBeDeleted -ne $null) {
 $ToBeDeleted | % {
 Remove-Item $_.FullName
 }
 }

}

And there you have it. Now the only thing between you and an IIS server that doesn’t require you to clean old log files is your task scheduler.

About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s