Joe-IT: Technology done right

Guerrilla Event Log archiving: why and how.

eventI am quite positive that there are as many solutions (both paid and unpaid) for handling Win32 Syslogs as there are SysAdmins out there. On my *NIX machines syslogs are a simple thing, configure Syslog-ng and move on. My Windows Syslogs are a whole different story.

First off, shame on you Microsoft for not providing built in syslogd integration capabilities. With the volume of BSD code in Windows there is just no acceptable reason for this.

But that doesn’t help me. The long term goal is of course to get a central Syslog server set up that will handle and archive log entries from all of my machines (*NIX and Win32), but that is going to take two things:

  1. Time I don’t have.
  2. Money I don’t have.

I need a solution for archiving my Windows event logs right now, in a central location, until I can get the central Syslog server set up. As I mentioned, most of the solutions for doing this on Windows machines (the ones I feel comfortable entrusting my event logs to anyway) cost somewhere in the neighborhood of an arm, a leg, and most of an ear, so those are not viable options. Now what do you do?

Well if you’re me, you roll your own solution. I’ve got several WS2003 servers that I need to log the event data from, because, well to be quite honest, because this network was built by someone that is more of a *NIX SysAdmin, and didn’t set up the Windows side correctly, so there are quite a few odd bugs in this network that will take quite a while to work out.

Now I could go through and manually export the event logs to a file once a month, but that is way too much work. I decided to script the solution to this problem using VBScript (as it is available on all of the Servers I need event log info from).

I give you logArchive.vbs:

'#==============================================================================
'#==============================================================================
'#  SCRIPT.........:  logArchive.vbs
'#  AUTHOR.........:  Joe Glessner
'#  EMAIL..........:  jglessner@gmail.com
'#  VERSION........:  1.0
'#  DATE...........:  30JUL07
'#  COPYRIGHT......:  2008, Joe-IT.com
'#  LICENSE........:  Freeware
'#  REQUIREMENTS...:
'#
'#  DESCRIPTION....:  This script backs up all of the event logs on the
'#                    designated computer, to the specified file server.
'#                    Optionally this script can also clear the event logs once
'#                    they are archived.
'#
'#  NOTES..........:
'#
'#  CUSTOMIZE......:
'#==============================================================================
'#  REVISED BY.....:
'#  EMAIL..........:
'#  REVISION DATE..:
'#  REVISION NOTES.:
'#
'#==============================================================================
'#==============================================================================
'**Start Encode**

'#==============================================================================
'#  START OF SCRIPT
'#==============================================================================
'Option Explicit
'On Error Resume Next

    '#--------------------------------------------------------------------------
    '#  SCRIPT CONFIGURATION SECTION
    '#--------------------------------------------------------------------------
    '#  OPTIONS:
    '#              strComputer = The name of the computer that generated the
    '#                            event logs (e.g. fs01 - use "." for the local
    '#                            machine.
    '#              objDir2 =      The destination directory on the file server.
    '#              clearEVTLogs   "No" does not clear the event logs. "Yes"
    '#                             will clear the event logs once the current
    '#                             logs are archived.
    '#--------------------------------------------------------------------------
    DIM strComputer, objDir2
    strComputer = "dc1"
    objDir2 = "\\SyslogServer\EventLogs$\" & strComputer
    clearEVTLogs = "Yes"

    '#--------------------------------------------------------------------------
    '#  Declare Remaining Variables
    '#--------------------------------------------------------------------------
    Dim current: current = Now
    Dim strDateStamp: strDateStamp = dateStamp(current)
    DIM objDir1: objDir1 = "\\" & strComputer & "\c$\EVT"

    '#--------------------------------------------------------------------------
    '#  Ensure that the Scratch directory exists on the source computer.
    '#--------------------------------------------------------------------------
    Set filesys=CreateObject("Scripting.FileSystemObject")
    If Not filesys.FolderExists(objDir1) Then
        createDir(objDir1)
    End If

    '#--------------------------------------------------------------------------
    '#  Ensure that the destination directory exists on the file server.
    '#--------------------------------------------------------------------------
    If Not filesys.FolderExists(objDir2) Then
        createDir(objDir2)
    End If

    '#--------------------------------------------------------------------------
    '#  Make create backups of the event logs to the Scratch directory.
    '#--------------------------------------------------------------------------
    strPath = objDir2 & "\"
    Set objWMIService = GetObject("winmgmts:" _
        & "{impersonationLevel=impersonate, (Backup, Security)}!\\" _
            & strComputer & "\root\cimv2")
    Set colLogFiles = objWMIService.ExecQuery _
        ("Select * from Win32_NTEventLogFile")
    For Each objLogfile in colLogFiles
        strCopyFile = strDateStamp & "_" & strComputer & "_" _
        & objLogFile.LogFileName & ".evt&"
        strBackupFile = "c:\EVT\" & strDateStamp & "_" _
            & strComputer & "_" & objLogFile.LogFileName & ".evt"
        strBackupLog = objLogFile.BackupEventLog _
            (strBackupFile)
        'WScript.Echo objLogFile.LogFileName & " backed up to " _
        '    & strBackupFile

        '#----------------------------------------------------------------------
        '#  Copy the event logs to the file server.
        '#----------------------------------------------------------------------
        call copyAFile(objDir1, strPath, strCopyFile)

        '#----------------------------------------------------------------------
        '#  Clear the event logs, or not.
        '#----------------------------------------------------------------------
        If clearEVTLogs = "Yes" then
            objLogFile.ClearEventLog()
        End If
    Next

'#==============================================================================
'#  SUBROUTINES/FUNCTIONS/CLASSES
'#==============================================================================
    '#--------------------------------------------------------------------------
    '#  FUNCTION.........:  dateStamp(ByVal dt)
    '#  PURPOSE..........:  Generate an 8-character date stamp from the current
    '#                      VBScript date.
    '#  ARGUMENTS........:  dt = The date stamp to convert.
    '#  EXAMPLE..........:  Dim current: current = Now
    '#                      WScript.Echo dateStamp(current)
    '#  REQUIREMENTS.....:
    '#  NOTES............:  The above example will produce output of 20080730 if
    '#                      run on 07/30/08.
    '#--------------------------------------------------------------------------
    Function dateStamp(ByVal dt)
        Dim y, m, d
        y = Year(dt)
        m = Month(dt)
        If Len(m) = 1 Then m = "0" & m
        d = Day(dt)
        If Len(d) = 1 Then d = "0" & d
        dateStamp = y & m & d
    End Function

    '#--------------------------------------------------------------------------
    '#  FUNCTION........:  copyAFile()
    '#  ARGUMENTS.......:  strScourceFolder = The folder containing the files to
    '#                                        be copied.
    '#                     strTargetFolder = The Destination Folder
    '#                     strFileName = The name and file extension of the file
    '#                                   to be copied.
    '#  PURPOSE.........:  General purpose file copying function.
    '#  EXAMPLE.........:  Wscript.Echo copyAFile("C:\", "\\Server\Share", _
    '#                     & "fileName.txt")
    '#  NOTES...........:  strSourceFolder folder must exist
    '#                     strTargetFolder folder must exist
    '#                     strFileName file must exist in strSourceFolder folder
    '#--------------------------------------------------------------------------
    Function copyAFile( Byval strSourceFolder, Byval strTargetFolder, _
        Byval strFileName)
        Dim objFSO, booOverWrite, strResult
        Set objFSO = CreateObject("Scripting.FileSystemObject")
        If objFSO.FileExists( strSourceFolder & "\" & strFileName) _
            And UCase( strSourceFolder)  UCase( strTargetFolder) Then
            If objFSO.FolderExists( strTargetFolder) Then
                Else
                strResult = "The destination folder does not exist!"
                'copyAFile = strResult
                Exit Function
            End If
            If objFSO.FileExists( strTargetFolder & "\" & strFileName) Then
                strResult = "The file exists, overwritten"
                booOverWrite = vbTrue
            Else
                strResult = "The file does not exist, created"
                booOverWrite = vbFalse
            End If
            objFSO.CopyFile strSourceFolder & "\" _
                & strFileName, strTargetFolder & "\", booOverWrite
        Else
            strResult = "The source file does not exist, or " _
                & "identical Source and Target folders!"
        End If
        'copyAFile = strResult
    End Function

    '#--------------------------------------------------------------------------
    '#  FUNCTION.......:  createDir(strDir)
    '#  ARGUMENTS......:  strDir = UNC path of the directory to create.
    '#  PURPOSE........:  Creates directories.
    '#  EXAMPLE........:  createDir("c:\WSH_TEST\")
    '#                    createDir("c:\WSH_TEST\" & "Files\")
    '#  NOTES..........:  If creating a subdirectory of a directory that does
    '#                    not exist, the parent directory must be created
    '#                    first, as shown in the example.
    '#--------------------------------------------------------------------------
    Function createDir(strDir)
        set filesys=CreateObject("Scripting.FileSystemObject")
        Set objFSO = CreateObject("Scripting.FileSystemObject")
        If Not filesys.FolderExists(strDir) Then
            Set objFolder = objFSO.CreateFolder(strDir)
        End If
    End Function

'#==============================================================================
'#  END OF FILE
'#==============================================================================

So, What does it do? This script will copy the event logs (well technically it creates a backup it doesn’t actually copy the data per se) from the target system to a directory defined by the user, and optionally clear the logs.

You can then use the built in Windows Event Log viewer to open the resulting file and search the event logs for the time period in the file.

How I use this:

I have several copies of this script set up in Windows’ Task Scheduler to run on the first of every month at exactly midnight, with the option to clear the event logs turned on. This allows me to create a Monthly archive of event logs for each Server that it is run against, and when I get a cryptic event log message like “Windows has previously logged the source of this error”, I can go back and search for the referenced previous entry.

Like I said before, this is a temporary system designed to do one thing: archive all of the Event logs from all of my Windows server to a central location until I can get a proper central Syslog server in place. It works flawlessly for the task it was designed to do.

end

November 10, 2008 Posted by Just Joe | Ask an IT ninja!!!, VBScript | | 7 Comments