解析类似 XML 的日志文件 [英] Parsing XML-Like log file

查看:62
本文介绍了解析类似 XML 的日志文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个记录事件的日志文件,如下所示.我想将每个事件转换为 PSCustomobject.它有点像 XML,但将 xml 转换为文件的 Get-Content 给了我一个错误:

I have a log file which records events as follows. I would like convert each event into a PSCustomobject. It kinda looks like XML but casting xml to the Get-Content for the file gives me an error:

无法将值System.Object[]"转换为类型System.Xml.XmlDocument".错误:此文档已有一个 'DocumentElement' 节点."

Cannot convert value "System.Object[]" to type "System.Xml.XmlDocument". Error: "This document already has a 'DocumentElement' node."

<event date='Jan 06 01:46:16' severity='4' hostName='ABC' source='CSMFAgentPolicyManager' module='smfagent.dll' process='AeXNSAgent.exe' pid='1580' thread='1940' tickCount='306700046' >
  <![CDATA[Setting wakeup time to 3600000 ms (Invalid DateTime) for policy: DefaultWakeup]]>
</event>

这是我到目前为止的一段代码

Here is the piece of code I have so far

   <#
.EXAMPLE    
source    : MaintenanceWindowMgr
process   : AeXNSAgent.exe
thread    : 8500
hostName  : ABC
severity  : 4
tickCount : 717008140
date      : Jan 10 19:45:00
module    : PatchMgmtAgents.dll
pid       : 11984
CData     : isAbidingByMaintenanceWindows() - yes
#>
$logpath = Join-Path $env:ProgramData 'Symantec\Symantec Agent\logs\Agent.log'
$hash=[ordered]@{};
$log = get-content $logpath | % {

    ## handle Event start
    ## sample: <event date='Jan 10 18:45:00' severity='4' hostName='ABC' source='MaintenanceWindowMgr' module='PatchMgmtAgents.dll' process='AeXNSAgent.exe' pid='11984' thread='8500' tickCount='713408140' >
    if ($_ -match '^<event') {

        if ($hash) {                
            ## Convert the hastable to PSCustomObject before clearing it
            New-Object PSObject -Property $hash
            $hash.Clear()
        }

        $line = $_ -replace '<event ' -replace ' >' -split "'\s" -replace "'"               
        $line | % { 

            $name,$value=$_ -split '='                
            $hash.$name=$value
        }        
    }

    ## handle CData
    ## Sample: <![CDATA[Schedule Software Update Application Task ({A1939DC8-DA4A-4E46-9629-0500C2383ECA}) triggered at 2014-01-10 18:50:00 -5:00]]>
    if ($_ -match '<!') {
        $hash.'CData' = ($_ -replace '<!\[CDATA\[' -replace '\]\]>$').ToString().Trim()
    }
}
  $log 

不幸的是,对象不是我想要的形式.

Unfortunately, the object is not in the form I would want it.

$log|gm


   TypeName: System.Management.Automation.PSCustomObject

Name        MemberType Definition                    
----        ---------- ----------                    
Equals      Method     bool Equals(System.Object obj)
GetHashCode Method     int GetHashCode()             
GetType     Method     type GetType()                
ToString    Method     string ToString()   

当我尝试从输出中收集所有对象时,我丢失了将哈希转换为 PSCustomObject 时生成的 NoteProperties

When I try to collect all the objects from the output, I am losing the NoteProperties that are generated when I convert the hash to PSCustomObject

   TypeName: System.Management.Automation.PSCustomObject

Name        MemberType   Definition                                                                                                                                     
----        ----------   ----------                                                                                                                                     
Equals      Method       bool Equals(System.Object obj)                                                                                                                 
GetHashCode Method       int GetHashCode()                                                                                                                              
GetType     Method       type GetType()                                                                                                                                 
ToString    Method       string ToString()                                                                                                                              
Equals      Method       bool Equals(System.Object obj)                                                                                                                 
GetHashCode Method       int GetHashCode()                                                                                                                              
GetType     Method       type GetType()                                                                                                                                 
ToString    Method       string ToString()                                                                                                                              
CData       NoteProperty System.String CData=isAbidingByMaintenanceWindows() - yes                                                                                      
date        NoteProperty System.String date=Jan 10 18:45:00                                                                                                             
hostName    NoteProperty System.String hostName=ABC                                                                                                             
module      NoteProperty System.String module=PatchMgmtAgents.dll                                                                                                       
pid         NoteProperty System.String pid=11984                                                                                                                        
process     NoteProperty System.String process=AeXNSAgent.exe                                                                                                           
severity    NoteProperty System.String severity=4                                                                                                                       
source      NoteProperty System.String source=MaintenanceWindowMgr                                                                                                      
thread      NoteProperty System.String thread=8500                                                                                                                      
tickCount   NoteProperty System.String tickCount=713408140 

我在这里错过了什么?

推荐答案

XML 文件必须具有单个根(或 documentElement)节点.由于您的日志文件似乎包含多个 <event> 标记而没有公共根元素,您可以像这样添加缺少的 documentElement:

XML files must have a single root (or documentElement) node. Since your log file seems to contain multiple <event> tags without a common root element you can add the missing documentElement like this:

$logpath  = Join-Path $env:ProgramData 'Symantec\Symantec Agent\logs\Agent.log'
[xml]$log = "<logroot>$(Get-Content $logpath)</logroot>"

之后,您可以使用通常的方法处理您的日志,例如:

After that you can process your log with the usual methods, e.g.:

$fmt = 'MMM dd HH:mm:ss'

$log.SelectNodes('//event') |
  select @{n='date';e={[DateTime]::ParseExact($_.date, $fmt, $null)}},
         severity, hostname, @{n='message';e={$_.'#cdata-section'}}

如果您更喜欢自定义对象,您可以像这样轻松创建它们:

If you prefer custom objects you can easily create them like this:

$fmt = 'MMM dd HH:mm:ss'

$log.SelectNodes('//event') | % {
  New-Object -Type PSObject -Property @{
    'Date'     = [DateTime]::ParseExact($_.date, $fmt, $null)
    'Severity' = $_.severity
    'Hostname' = $_.hostname
    'Message'  = $_.'#cdata-section'
  }
}

这篇关于解析类似 XML 的日志文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆