Skip to main content

Using Text Based Logs with Windows PowerShell (5 of 8)


Day 5: Turning Multi-line Text Based Logs into PowerShell Objects.
Over the previous few days, we have been working to convert a text based log file that contains one record per line into a PowerShell object.  Now we are going to take it to the next level.  As a Network Administrator, I have come across log files that spread their information onto multiple lines.  We are going to use the same set of steps as before:
1.       Identify a rule to separate records
2.       Identify a rule to separate property names from property values
3.       Create an object that contains all possible property names.
4.       Read the log records into the object.
5.       Send to the pipeline.
We are going to build the cmdlet Import-MyLog2.  We will be using the txt file called Data2.txt, which you can see below.
Log Example 2: Records on multiple lines with inconsistent properties:
Server Blade #7 Information:
        Server Blade Type: No Server Blade Installed
 
Server Blade #8 Information:
        Type: Server Blade
        Manufacturer: HP
        Product Name: ProLiant BL480c G1
        Part Number: 404707-B21
        System Board Spare Part Number: 438453-001
        Serial Number: 9999999999
        UUID: 37343034-3730-4247-3837-999999999999
        Server Name: SRV000001
        Asset Tag: [Unknown]
        ROM Version: I14 10/25/2010
 
        CPU 1: Dual-Core Intel Xeon 3000 MHz
        CPU 2: Dual-Core Intel Xeon 3000 MHz
        Memory: 49152 MB
 
        Embedded Ethernet
            NIC 1: 00:19:BB:34:61:1C
            NIC 2: 00:19:BB:34:41:24
            NIC 3: 00:19:BB:29:92:37
            NIC 4: 00:19:BB:29:92:38
          iSCSI 1: 00:19:BB:34:61:1D
          iSCSI 2: 00:19:BB:34:41:25
 
        Mezzanine 2: QLogic QMH2462 4Gb FC HBA for HP c-Class BladeSystem
           Port 1: 50:06:0b:00:00:6b:d3:9c
           Port 2: 50:06:0b:00:00:6b:d3:9e
 
Management Processor Information:
        Type: iLO2
        Name: SRV000001-i
        Firmware Version: 2.12 Jul 16 2012
        IP Address: 10.199.10.240
        MAC Address: 00:19:AA:34:21:99
        Power Management Controller Version: 0.5
 
Server Blade #9 Information:
        Server Blade Type: Bay Subsumed
 
Server Blade #10 Information:
        Server Blade Type: Bay Subsumed
 
Server Blade #11 Information:
        Type: Server Blade
        Manufacturer: HP
        Product Name: ProLiant BL460c Gen8
        Part Number: 641016-B21
        System Board Spare Part Number: 719592-001
        Serial Number: 9999999999
        UUID: 30313436-3631-5A43-3332-99999999999
        Server Name: SRV0000002
        Asset Tag: [Unknown]
        ROM Version: I31 08/20/2012
 
        CPU 1:  Intel(R) Xeon(R) CPU E5-2609 0 @ 2.40GHz (4 cores)
        CPU 2:  Intel(R) Xeon(R) CPU E5-2609 0 @ 2.40GHz (4 cores)
        Memory: 16384 MB
 
        FLB Adapter 1: HP FlexFabric 10Gb 2-port 554FLB Adapter
         Ethernet FlexNIC (NIC 1) LOM1:1-a    6C:3B:E5:A9:DB:B0
         Ethernet FlexNIC (NIC 3) LOM1:1-b    6C:3B:E5:A9:DB:B1
         Ethernet FlexNIC (NIC 5) LOM1:1-c    6C:3B:E5:A9:DB:B2
         Ethernet FlexNIC (NIC 7) LOM1:1-d    6C:3B:E5:A9:DB:B3
         Ethernet FlexNIC (NIC 2) LOM1:2-a    6C:3B:E5:A9:DB:B4
         Ethernet FlexNIC (NIC 4) LOM1:2-b    6C:3B:E5:A9:DB:B5
         Ethernet FlexNIC (NIC 6) LOM1:2-c    6C:3B:E5:A9:DB:B6
         Ethernet FlexNIC (NIC 8) LOM1:2-d    6C:3B:E5:A9:DB:B7
 
        This server does not contain any mezzanine cards
 
Management Processor Information:
        Type: iLO4
        Name: SRV0000002_i
        Firmware Version: 1.10 Jul 17 2012
        IP Address: 20.199.8.40
        MAC Address: 10:61:4B:AD:C2:A7
        Power Management Controller Version: 3.0
 
 
 
 
We will be reusing the function Get-Log without any alterations from the previous code.  Please refer to day 2 if you need to brush up on this function.
 
We will also use a Get-Records function, but this time we have to deal with discovering when a record begins, and where it ends.  Let’s start by defining our rule to determine the start of a record. I can see that a string of text “Server Blade” is common at the start of all records. I also notice that records for Server Blade #9 and #10 also has a property field that contains this pattern.  To determine the record start, I will have to use the patter “Server Blade #* Information:” to define each record.
 
Two other items to note.  The blade number is a potential property that we will address when we create our custom property.  Also, there is an extra line of nothing at the end of each record that we will want to filter out.  At first you may be thinking that we can use this black line as a delimiter between records.  Looking more carefully at the entire set of data, we see blank lines between valid properties in the same object. 
 
So, we will create an object to send back to the calling statement with two properties.  The first is the index number that starts a record and the second which is the index number of the start of the next record minus 1.  For the last record, we will use the number of lines in the record to mark its end.
 
    Function Get-RecordIndex
    {
    Param ($Log)
    # Determines the index number of where each record starts and ends.
    # Returns an object with the start and end index number of
    # each record.
 
        # Array to hold all of the objects.
        $Object = @()
       
        # Find the start of each record.
        For($X=0;$X -lt $Log.Count; $X++)
        {
            If($Log[$X] -like "Server Blade #* Information:")
            {
 
                $Obj = New-Object -TypeName PSObject
                $Obj | Add-Member -NotePropertyName "Start" `
                                  -NotePropertyValue $X
                $Obj | Add-Member -NotePropertyName "End" `
                                  -NotePropertyValue $Null
                $Object += $Obj
            }
        } # End: For($X=0;$X -lt $Log.Count; $X++)
 
        # Derive the end of each record.
        For ($X = 0; $X -lt $Object.Count - 1; $X++)
        {
            $Object[$X].End = $Object[$X+1].Start -1
        } # End: For ($X = 0; $X -lt $Object.Count; $X++)
 
        # Add the final End value as the end of the log file.
        $Object[$Object.count-1].End = $Log.count
 
        # Return the object to the calling statement.
        Write-Output $Object
       
    } # End: Function Get-RecordIndex
 
In the above example, you can see the three stages that we need to go through to find the index numbers of the start and end of each record.  Each line of the log file is assigned an index number starting with 0.  The first stage will find the start of each record.  Once the start is found, then an object is created with that index number as the Start property and a Null value set as the End property.  The next stage derives the End value from the next records Start value.   The third stage will add the final objects End value as the number of indexes in the log.
 
Tomorrow we will look at how to derive our properties.

Comments

Popular posts from this blog

How to list all the AD LDS instances on a server

AD LDS allows you to provide directory services to applications that are free of the confines of Active Directory.  To list all the AD LDS instances on a server, follow this procedure: Log into the server in question Open a command prompt. Type dsdbutil and press Enter Type List Instances and press Enter . You will receive a list of the instance name, both the LDAP and SSL port numbers, the location of the database, and its status.

How to run GPResult on a remote client with PowerShell

In the past, to run the GPResult command, you would need to either physically visit this client, have the user do it, or use and RDP connection.  In all cases, this will disrupt the user.  First, you need PowerShell remoting enabled on the target machine.  You can do this via Group Policy . Open PowerShell and type this command. Invoke-Command –ScriptBlock {GPResult /r} –ComputerName <ComputerName> Replace <ComputerName> with the name of the target.  Remember, the target needs to be online and accessible to you.

Error icon when creating a GPO Preference drive map

You may not have an error at all.  Take a look at the drive mapping below. The red triangle is what threw us off.  It is not an error.  It is simply a color representation of the Replace option of the Action field in the properties of the drive mappings. Create action This give you a green triangle. The Create action creates a new mapped drive for users. Replace Action The Replace action gives you a red triangle.  This action will delete and recreate mapped drives for users. The net result of the Replace action is to overwrite all existing settings associated with the mapped drive. If the drive mapping does not exist, then the Replace action creates a new drive mapping. Update Action The Update action will have a yellow triangle. Update will modify settings of an existing mapped drive for users. This action differs from Replace in that it only updates settings defined within the preference item. All other settings remain as configured on the mapped drive. If the