Hey, Scripting Guy! How Can I Check the Size of My Event Log and Then Backup and Archive It If It Is More Than Half Full?

ScriptingGuy1

Hey, Scripting Guy! Question

Hey, Scripting Guy! We have recently enabled additional security auditing on our network, and I do not want to increase the size of those logs due to the fact that they are already huge. I do not want to turn on circular logging because I need to keep an audit trail for compliance reasons. I need to write a script that I use to check the size of the security event log. If it is more than 50 percent full, I want to backup the log, and then empty the log. I do not know if this is even possible to do via script, but if it were, it would save me several hours of work a week because this is the exact task that I have to do manually every morning and afternoon.

– DP

SpacerHey, Scripting Guy! Answer

Hi DP,

I know what it is like to be chained to a desk all day. If I could write a script to answer all e-mail that is sent to scripter@microsoft.com, it would be cool. Of course, then I would miss out on one of my favorite things to do. I love reading the scripter e-mail because I hear from people all over the world who are victims of bad situations. Sometimes, these are due to strange management decisions (such as “we will not lock down the desktop because it is incompatible with the team concept”). “We trust our employees”—you know what happens then don’t you? The poor IT pro spends all his or her time fixing stupid mistakes made by clueless users. And as a result that IT pro has no time to spend planning deployments, patching updates, or evaluating new technology. Short of changing jobs what can you do? There are lots of ideas I have come up with over the years, and many of them involve a carefully crafted script such as the one I wrote for you, DP. This one is pretty cool; it looks at the size of the event log. If the event log is more than half full, we backup and archive it.

This week is Event Log Week. We have quite a few good scripts that work with event logs in the Script Center Script Repository. The Scripting Guide has some good information about querying event logs, managing event logs, and writing to event logs from a VBScript perspective. These same types of information are covered from a Windows PowerShell perspective in chapter 3 of the Windows PowerShell Scripting Guide. Over the years, there have been a few “Hey, Scripting Guy!” articles on topics such as finding the oldest event in an event log, the newest event in an event log, backing up the event log to a text file, retrieving audit failures from the event log, or retrieving all failures from the security event log. There is also the Log Parser 2.2, and we have a number of examples on the Script Center of how to use Log Parser. The scripts this week are written in Windows PowerShell. If you need help converting VBScript to Windows PowerShell, you can refer to this conversion guide.

We decided to call the script BackUpAndClearEventLog.ps1, probably because it backs up and clears an event log (go figure). We do not have this exact script in VBScript version, although here is a script that clears an event log based upon size. The event log portion of the Script Center Script Repository is a nice place to find a good sampling of things you can do with managing event logs. The BackUpAndClearEventLog.ps1 script is seen here:

Param($logName = “security”,$backupFolder = “C:\backupLogs”)

Function Get-EventLog([string]$logName) { $log = Get-WmiObject -Class Win32_NTEventLogFile -filter “LogFileName = ‘$logName'” If($log.MaxFileSize / $log.FileSize -ge 50) { “Log is half full. Backing up now.” Backup-EventLog($log) } #end if Else { “Not backed up: $logName is only ” + ($log.MaxFileSize / $log.FileSize).tostring(“N2″) + ” percent full” } #end else } #end Get-EventLog

Function Backup-EventLog($log) { $folder = Join-Path -Path $BackUpFolder -ChildPath (Get-Date).ToString(“MMddyy_hhmm”) If(-not(Test-Path $folder)) { New-Item -path $folder -itemtype Directory -force | out-Null } $rtn = $log.BackupEventLog(“$folder\$logName.evt”).ReturnValue If($rtn -eq 0) { $log.ClearEventLog() | out-null } #end if ELSE { “$logName could not be cleared. Backup ended with $($rtn)” } } #end Backup-EventLog

# *** ENTRY POINT *** Get-EventLog -logname $logname

The first thing that we need to do is to define the command-line parameters that the script will accept. For this script, we wish to accept two input parameters. The first parameter is the name of the log that we will work with. We call this parameter $logname. The second parameter we will define is used to specify the path to the backup files. We’ll call this parameter $backupfolder. For each of these parameters, we have also defined default values. These default values will be used if the script is called without any modification. This code is seen here:

Param($logName = “security”,$backupFolder = “C:\backupLogs”)

The first function that we would like to create is called the Get-EventLog function and it receives a single input when the function is called. The input that is stored in the variable $logName is a string data type. Because of this we use a type constraint to control the type of data that can be passed to the function. As always when we create a function, we must use the function keyword as seen here:

Function Get-EventLog([string]$logName)
 {

After we begin the function, we now use the Get-WmiObject cmdlet with the class parameter to allow us to access the WMI information that is related to the event log. The WMI class that we need to use is the Win32_NTeventlogfile class. Because there are a number of the event log files on the computer we need to use the filter parameter to limit our results to only a specific file. To do this we use the Logfilename property and specify the name that we have stored in the $logName variable. This is seen here:

$log = Get-WmiObject -Class Win32_NTEventLogFile -filter “LogFileName = ‘$logName'”

The Windows event log we are working with is seen in the Event Viewer utility here:

Image of the Windows event log

 

After we have stored the WMI object in the $log variable, we use the if statement and examine the MaxFileSize property. We then divide this property value by the FileSize property. If the resulting number is greater than 50, we will proceed to back up the file. This is seen here:

If($log.MaxFileSize / $log.FileSize -ge 50)
 {

The first thing that we want to do is to provide a status message to the user. In our example, we use a simple string that states the log is half full and we are backing it up now. After we have displayed this information, we call the Backup-EventLog function and pass the WMI object that is contained in the $log variable to the function. After we have passed the object to the Backup-EventLog function, we end our if statement by closing the curly brackets. This is seen here:

“Log is half full. Backing up now.”
   Backup-EventLog($log)
  } #end if

Now it is time to consider alternative scenarios. If the log is less than half full, we display a status message that states that the log is not backed up. We supply the name of the log and the actual size that is contained in the MaxFileSize property of the $log object. We then calculate the percentage of the log size in relationship to the maximum file size that the log is permitted to grow. We display a formatted number by using the tostring method of the object. Inside the smooth parentheses of the tostring method, we use a format specifier from the .NET Framework. The letters used for the format specifier are case sensitive. The capital N followed by the number 2 indicates that the number will be displayed with only two numbers trailing the decimal point. This is shown here:

Else 
  { 
   “Not backed up: $logName is only ” + ($log.MaxFileSize / $log.FileSize).tostring(“N2″) +  ” percent full” 
  } #end else
} #end Get-EventLog

We now need to create the Backup–EventLog function. To do this we use the Function keyword followed by the name of the function that we will create. The Backup–EventLog function will accept a single parameter, which is the object that is stored in the $log variablevariable:

Function Backup-EventLog($log)
{

Next we need to create the path that will be used to hold the backup file. To do this we use the Join-Path cmdlet and use the path parameter to specify the parent folder for the backup. The child folder is created based upon the date. To create the name for the child folder we use the Get–Date cmdlet and feed the date time object to the tostring method. Inside the parentheses of the tostring method, we once again use a .NET Framework format specifier. The capital M is used to indicate the month, the lowercase d is used for the day, and the lowercase y indicates the year. The lowercase h is the hour and the lowercase m stands for the minutes. Because two letters are used in the pattern, it indicates that two numbers will be represented. This is seen here:

$folder = Join-Path -Path $BackUpFolder -ChildPath (Get-Date).ToString(“MMddyy_hhmm”)

If the folder does not exist, we create it. We use the Test-Path cmdlet to see if the folder exists. If the folder does not exist, we use the New-Item cmdlet to create the new folder. Because we do not want to see the feedback from the command, we pipeline the output to the Out-Null cmdlet:

If(-not(Test-Path $folder)) 
   { 
     New-Item -path $folder -itemtype Directory -force | out-Null
   }

The BackupEventLog method is used to (shocking, we know) back up the event log. The method receives the path as well as the file name and extension for the backup file. When the method is called, it returns an object that indicates the status of the method call. We’re interested in a return code of zero, which means there were no errors. We store the return code in the $rtn variable:

$rtn = $log.BackupEventLog(“$folder\$logName.evt”).ReturnValue

After the destination folder has been created and the event log backed up, the directory structure looks similar to the one seen here:

Image of the directory structure

 

If the $rtn variable is equal to zero, we empty the event log by using the ClearEventLog method. There are no parameters for this method, so the parentheses used for the method are empty. The ClearEventLog method does return an error code; however, we are not interested in this, so we pipeline it to the Out-Null cmdlet. This is seen here:

If($rtn -eq 0)
    {
     $log.ClearEventLog() | out-null
    } #end if

If the backup was not successful, the value contained in the $rtn variable will not be equal to zero. If this is the case, we do not clear the event log, so we must print a message to this effect:

ELSE 
   {
    “$logName could not be cleared. Backup ended with $($rtn)” 
  }
} #end Backup-EventLog

We are now at the entry point to the script. Everything we have seen so far is a lot of preparatory work. The script executes by calling the Get-EventLog function and passing the log name, which is contained in the $logname variable. This is seen here:

Get-EventLog -logname $logname

Well, DP, we have created a script that looks at the size of an event log, and if the log is more than half full, it backs up the log and then empties it. It was a fun and interesting scenario. Join us tomorrow as we continue with Event Log week. Until then, take care.

 

Ed Wilson and Craig Liebendorfer, Scripting Guys

0 comments

Discussion is closed.

Feedback usabilla icon