查找日志文件中大于定义时间的条目

时间:2016-05-25 12:38:21

标签: powershell datetime tomcat

我的公司需要分析Tomcat的日志文件以检查特定错误并使用Powershell。这些错误将存储在一个数组中,并以1:1进行检查。使用Windows任务计划程序每30分钟发生一次。如果在日志文件中发现此类错误,则生成的文本文件将发送给管理员。

然而,仅在过去30分钟内检查错误是有意义的,而不是事先。

所以我先定义了一个变量:

$logTimeStart = (Get-Date).AddMinutes(-30).ToString("yyyy-MM-dd HH:mm:ss")

稍后我会检查是否存在这样的错误:

$request = Get-Content ($logFile) | select -last 100 | where  { $_ -match $errorName -and $_ -gt $logTimeStart }

不幸的是,这不起作用;它还会在30分钟的间隔之前发送错误。

以下是Tomcat日志的摘录:

2016-05-25 14:21:30,669 FATAL [http-apr-8080-exec-4] admins@company.de de.abc.def.business.service.ExplorerService GH00000476: 
de.abc.def.business.VisjBusinessException: Invalid InstanceId 
    at de.abc.def.business.service.ExplorerService$ExplorerServiceStatic.getExplorer(ExplorerService.java:721)
    at de.abc.def.business.service.ExplorerService$ExplorerServiceStatic.getTreeItemList(ExplorerService.java:823)
    at sun.reflect.GeneratedMethodAccessor141.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at de.abc.def.business.provider.ServiceProvider.callServiceMethod(ServiceProvider.java:258)
    at de.abc.def.business.communication.web.client.ServiceDirectWrapperDelegate.callServiceMethod(ServiceDirectWrapperDelegate.java:119)
    at de.abc.def.business.communication.web.client.ServiceWrapperBase.callServiceMethod(ServiceWrapperBase.java:196)
    at de.abc.def.business.communication.web.client.ServiceDirectWrapper.callServiceMethod(ServiceDirectWrapper.java:24)
    at de.abc.def.web.app.service.stub.AbstractBaseStub.callServiceMethodDirect(AbstractBaseStub.java:72)
    at de.abc.def.web.app.service.stub.AbstractBaseStub.callServiceMethod(AbstractBaseStub.java:183)
    at de.abc.def.web.app.service.stub.StubSrvExplorer.getTreeItemList(StubSrvExplorer.java:135)
    at de.abc.def.web.app.resource.servlet.ExplorerServlet.createXml(ExplorerServlet.java:350)
    at de.abc.def.web.app.resource.servlet.ExplorerServlet.callExplorerServlet(ExplorerServlet.java:101)
    at de.abc.def.web.app.resource.servlet.VisServlet.handleServlets(VisServlet.java:244)
    at de.abc.def.web.app.FlowControlAction.isPing(FlowControlAction.java:148)
    at de.abc.def.web.app.FlowControlAction.execute(FlowControlAction.java:101)
    at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484)
    at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274)

不幸的是,人们不能说会出现多少行这样的错误。因此100只是一个估计(效果很好)。

那么如何更改相关的行

$request = Get-Content ($logFile) | select -last 100 |
           where  { $_ -match $errorName -and $_ -gt $logTimeStart }

到正确的一个?

1 个答案:

答案 0 :(得分:1)

使用Select-String和正则表达式来解析日志文件。基本上,日志条目包括时间戳,严重性和消息(可能跨越多行)。正则表达式可能如下所示:

(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3})\s+(\w+)\s+(.*(?:\n\D.*)*(?:\n\t.*)*)

(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3})与时间戳匹配 (\w+)符合严重程度 (.*(?:\n\D.*)*)匹配日志消息(当前行后跟零行或多行不以数字开头)。

每个子表达式周围的括号将子匹配捕获为一个组,然后可以用它来填充自定义对象的属性。

$datefmt = 'yyyy-MM-dd HH:mm:ss,FFF'
$culture = [Globalization.CultureInfo]::InvariantCulture
$pattern = '(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3})\s+(\w+)\s+(.*(?:\r\n\D.*)*)'
$file    = 'C:\path\to\your.log'

Get-Content $file -Raw | Select-String $pattern -AllMatches | ForEach-Object {
  $_.Matches | ForEach-Object {
    New-Object -Type PSObject -Property @{
      Timestamp = [DateTime]::ParseExact($_.Groups[1].Value, $datefmt, $culture)
      Severity  = $_.Groups[2].Value
      Message   = $_.Groups[3].Value
    }
  }
}

实际上并不需要将日期子字符串解析为DateTime值(因为即使使用字符串比较,ISO格式的日期字符串也可以正确排序),但这样做很好,所以你不必转换您的参考时间戳为格式化字符串。

请注意,您需要将整个日志文件作为单个字符串读取才能使其正常工作。在PowerShell v3及更高版本中,可以通过使用参数Get-Content调用-Raw来实现。在早期版本中,您可以通过Get-Content cmdlet管道Out-String的输出以获得相同的结果:

Get-Content $file | Out-String | ...