【发布时间】:2015-05-19 07:37:42
【问题描述】:
我用 Powershell 编写了一个日志tailer,tailer 加载到一个 xml 文件中,该文件包含有关何时报告日志尾部中的单词匹配的配置信息(基本上,如果某些模式在尾部出现 X 次)。
目前,tailer 没有为许多包含匹配项的行返回匹配项。
例如,我们正在检索一个包含许多 INFO 行的日志文件,如果我检查单词 INFO 没有检测到任何东西,但是如果我查找工作 shutdown 它返回匹配项(带有 shutdown 的行还包含该行的 INFO) .
真正奇怪的是,在我自己的机器上使用相同的日志文件和相同的 Powershell 脚本似乎可以产生完全准确的结果,但在服务器上却表现得很奇怪。
我怀疑这可能是服务器上运行的 Powershell 版本的问题,所以我希望这里的人可能知道可能会出现不同版本的问题。我还注意到,当我打印出匹配的数量时,如果没有找到输出是空白的,也许这应该是 0 并导致一些奇怪的问题触发?
function Main()
{
#### GLOBAL SETTINGS
$DebugPreference = "Continue"
$serverName = $env:COMPUTERNAME
$scriptPath = Split-Path $script:MyInvocation.MyCommand.Path
$logConfigPath = "$scriptPath/config.xml"
#### VARIABLES RELATING TO THE LOG FILE
#contains the log path and log file mask
$logPaths = @()
$logFileMasks = @()
# the total number of lines grabbed from the end of the log file for evaluation
$numLinesToTail = 1000
# key value pair for the strings to match and the max count of matches before they are considered an issue
$keywords = @()
$maxCounts = @()
#### VARIABLES RELATING TO THE EMAIL SETTINGS
$smtpServer = "mail server"
$emailSubject = "$serverName log report"
$toEmailAddress = "email accounts"
$fromEmailAddress = ""
# any initial content you want in the email body should go here (e.g. the name of the server that this is on)
$htmlBodyContent = "<p><h3>SERVER $serverName : </h3></p><p>Items that appear in red have exceeded their match threshold and should be investigated.<br/>Tail Lines: $numLinesToTail</p>"
#### FUNCTION CALLS
LoadLogTailerConfig $logConfigPath ([ref]$logPaths) ([ref]$logFileMasks) ([ref]$keywords) ([ref]$maxCounts)
for ($i = 0; $i -lt $logPaths.Count; $i++)
{
$tail = GetLogTail $numLinesToTail $logPaths[$i] $logFileMasks[$i]
$tailIssueTable = CheckForKeywords $tail $keywords[$i] $maxCounts[$i]
if ($tailIssueTable -ne "")
{
$htmlBodyContent += "<br/>Logs scanned: " + (GetLatestLogFileFullName $logPaths[$i] $logFileMasks[$i]) + "<br/><br/>" + $tailIssueTable
SendIssueEmail $smtpServer $emailSubject $toEmailAddress $ccEmailAddress $fromEmailAddress $htmlBodyContent
}
}
}
# Loads in configuration data for the utility to use
function LoadLogTailerConfig($logConfigPath, [ref]$logPaths, [ref]$logFileMasks, [ref]$keywords, [ref]$maxCounts)
{
Write-Debug "Loading config file data from $logConfigPath"
[xml]$configData = Get-Content $logConfigPath
foreach ($log in $configData.Logs.Log) {
$logPaths.Value += $log.FilePath
$logFileMasks.Value += $log.FileMask
$kwp = @()
$kwc = @()
foreach ($keywordSet in $log.Keywords.Keyword)
{
$kwp += $keywordSet.Pattern
$kwc += $keywordSet.MaxMatches
}
$keywords.Value += @(,$kwp)
$maxCounts.Value += @(,$kwc)
}
}
# Gets a string containing the last X lines of the most recent log file
function GetLogTail($numLinesToTail, $logPath, $logFileMask)
{
$logFile = GetLatestLogFileFullName $logPath $logFileMask #Get-ChildItem $logPath -Filter $logFileMask | sort LastWriteTime | select -Last 1
Write-Debug "Getting $numLinesToTail line tail of $logFile"
$tail = Get-Content "$logFile" | select -Last $numLinesToTail
return $tail
}
function GetLatestLogFileFullName($logPath, $logFileMask)
{
$logFile = Get-ChildItem $logPath -Filter $logFileMask | sort LastWriteTime | select -Last 1
return "$logPath$logFile"
}
# Returns body text for email containing details on keywords in the log file and their frequency
function CheckForKeywords($tail, $keywords, $maxCounts)
{
$issuesFound = 0
$htmlBodyContent += "<table><tr><th style=""text-align : left;"">Keyword</th><th>Max Count Value</th><th>Count Total<th></tr>"
for ($i = 0; $i -lt $keywords.Count; $i++)
{
$keywordCount = ($tail | Select-String $keywords[$i] -AllMatches).Matches.Count
Write-Debug (("Match count for {0} : {1}" -f $keywords[$i], $keywordCount))
if ($keywordCount -gt $maxCounts[$i])
{
# style red if the count threshold has been exceeded
$htmlBodyContent += "<tr style=""color : red;""><td>" + $keywords[$i] + "</td><td>" + $maxCounts[$i] + "</td><td>" + $keywordCount + "</td></tr>"
$issuesFound = 1
}
else
{
# style green if the count threshold has not been exceeded
$htmlBodyContent += "<tr style=""color : green;""><td>" + $keywords[$i] + "</td><td>" + $maxCounts[$i] + "</td><td>" + $keywordCount + "</td></tr>"
}
}
$htmlBodyContent += "</table>"
if ($issuesFound -eq 1)
{
return $htmlBodyContent
}
return ""
}
# Sends out an email to the specified email address
function SendIssueEmail($smtpServer, $subject, $toAddress, $ccAddress, $fromAddress, $bodyContent)
{
Write-Debug "Sending email with subject: $subject, To: $toAddress, via SMTP ($smtpServer)"
Send-MailMessage -SmtpServer $smtpServer -Subject $subject -To $toAddress -From $fromAddress -BodyAsHtml $bodyContent
}
cls
Main
还有一个 XML 配置示例:
<Logs>
<Log>
<FilePath>C:/Some/Path</FilePath>
<FileMask>log.*</FileMask>
<Keywords>
<Keyword>
<Pattern>NullReferenceException</Pattern>
<MaxMatches>10</MaxMatches>
</Keyword>
<Keyword>
<Pattern>Exception</Pattern>
<MaxMatches>10</MaxMatches>
</Keyword>
</Keywords>
</Log>
<Log>
<FilePath>C:/Some/Path</FilePath>
<FileMask>test.*</FileMask>
<Keywords>
<Keyword>
<Pattern>NullReferenceException</Pattern>
<MaxMatches>100</MaxMatches>
</Keyword>
</Keywords>
</Log>
</Logs>
编辑:有问题的服务器正在运行 Powershell V 1.0,但是测试服务器也运行相同的版本非常好......
【问题讨论】:
-
这就是重现您的问题所需的全部内容吗?如果您怀疑版本可能是一个因素,最好包含相关版本。
-
乍一看,您可能对变量范围有疑问。较新版本的 PoweShell (v3,v4) 对变量范围有更严格的限制(仅我的轶事经验)。特别要检查 $keywords 和 $maxCounts 是否可以在函数 LoadLogTailerConfig 中实际访问。这可能因 PowerShell 版本而异。
-
@JanChrbolka 如果是这种情况,虽然我不应该有任何关键字得到匹配,但是其中一些得到匹配,而同一行上的其他关键字没有被检测到......
-
您能在问题中添加一个简短的示例日志文件吗?
-
@JanChrbolka 可能不是一个好主意,因为它可能会带来安全风险,但是它们确实是相当标准的日志,它们具有以下格式:
其中 LogType 是 INFO错误调试等和消息包含异常或其他信息
标签: regex xml powershell