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

标签 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)

Unfortunately one cannot say how many lines of such an error will show up. Therefore 100 is just an estimate (which works well).

So how to change the related line

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

一个正确的?

最佳答案

使用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}) matches the timestamp.
(\w+) matches the severity.
(.*(?:\n\D.*)*) matches the log message (the current line followed by zero or more lines not beginning with a number).

The parentheses around each subexpression capture the submatch as a group that can then be used for populating the properties of custom objects.

$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 和更新版本中,这可以通过使用参数 -Raw 调用 Get-Content 来实现。在早期版本中,您可以将 Get-Content 的输出通过 Out-String cmdlet 进行管道传输以获得相同的结果:

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

关于powershell - 在日志文件中查找大于定义时间的条目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37437422/

相关文章:

asp.net-mvc - MVC3在opera中将值设置为文本框类型日期时间

javascript - 加载 css 和 js

Powershell:将对象[]输出到文件

java - Android 中的埃塞俄比亚日历

sql - 计算日期之间的差异 - Postgres

tomcat - 在具有简单 POJO 类的 Tomcat 中使用 CDI(焊接)

java - 为什么我们需要两次在 tomcat logging.properties 中写入处理程序?

windows - 在 Windows 批处理中使用 PowerShell 命令和反引号换行符

sql-server - powershell 从表中提取值

powershell - 使用 PowerShell 替换文本文件中的字符串