【发布时间】:2013-07-24 15:11:56
【问题描述】:
我们有 2 个 SMTP 网关,它们可以输出文本 .log 文件(通常每次弹出大约 10-30MB)来存储大约一周的数据。总的来说,两者的大小通常约为 1.2GB。
我在日志目录中设置了 (2) 个只读共享,并且正在尝试使用 Select-String 解析日志条目(例如,假设我想查看是否收到了“bdole”的电子邮件。如果我想要的是简单地获得行号的点击率,这还不错。
但是,我想获取整个“日志条目”。我最初的研究表明我需要立即阅读整个日志的内容,然后针对它执行正则表达式。所以,这就是我正在做的,将近 200 个文件。
但是,我不认为 i/o 才是真正的问题。我正在生成约 200 个线程(每个文件一个)并限制为 20 个线程。最初的 20 个线程需要一些时间才能运行。我输入了一些调试代码并回到单线程;似乎简单地正则表达式一个 10-20MB 文件的内容需要很长时间。
我怀疑我编写的正则表达式在速度方面非常不足(如果我让它运行一夜,它就可以正常工作。)另外,网络 I/O 非常低(峰值在2Ggpbs 连接的 0.6%),而 CPU/RAM 非常高。
理想的日志条目如下所示:
---- SMTPRS log entry made at mm/dd/yyyy HH:mm:ss
Incoming SMTP call from x.x.x.x at HH:mm:ss.
<<< 220 mail.foo.com
>>> QUIT
<<< 221 mail.foo.com closing
Incoming SMTP call from x.x.x.x completed at HH:mm:ss.
唯一可靠的分隔符是开头的----(有时它会/不会以----结尾)
“日志条目”的内容可以是非常多变的,包括阻塞连接的通知等。
我正在使用的正则表达式
(?sm)----((?!----).*?)(log entry)((?!----).*?)(#USERINPUT#)((?!----).*?)----
#USERINPUT# 被传递给脚本的内容替换。
解析代码
使用gci 获取文件路径列表后
if ( !(Test-Path $path) ) {
write-error "issue accessing $path"
} else {
try {
$buffer = [io.file]::ReadAllText($path)
}
catch {
$errArray += $path
$_
}
[string[]]$matchBuffer = @()
$matchBuffer += $entrySeperator
$matchBuffer += $_
$matchBuffer += $entrySeperator
$matchBuffer += $buffer | Select-String $regex -AllMatches |
% {$_.Matches} |
% {$_.Value; $entrySeperator}
if ($errArray) {
write-warning "There were errors, probably in accessing files. "
$errArray
}
$fileName = (gi $path).Name
sc -path $tmpDir\$fileName -value $matchBuffer
$matchBuffer | Out-String
我几乎想知道解析“命中”(例如第 21 行上的 XXXX.LOG)并从上下文向后重建日志条目是否会更快/更好。
【问题讨论】:
-
您是否被锁定在使用 PowerShell 将日志解析为纯非结构化文本?必须有其他更适合挖掘此类日志数据的工具/系统/平台。
标签: regex powershell logging