使日志阅读高效

时间:2011-08-11 14:16:39

标签: .net perl scripting powershell

我有一个用于监视数据库的perl脚本,我正在尝试将其编写为powershell脚本。

在perl脚本中有一个函数可以读取错误日志并过滤掉重要的内容并将其返回。它还保存日志文件的当前位置,以便下次必须读取日志时,它可以从它离开的位置开始,而不是再次读取整个日志。这是通过使用 tell 函数完成的。

我有一个想法是使用Get-Content cmdlet,并开始在最后一个位置读取,处理每一行直到文件末尾,然后保存位置。

您是否知道任何技巧,以便我可以在阅读后获取日志文件中的位置并在特定位置开始阅读。

或者有更好和/或更简单的方法来实现这一目标吗?

吉斯利

编辑:这必须通过脚本完成,而不是通过其他工具完成。

编辑:所以我正在使用.NET API,但它并不适合我。 我找到了有用的链接herehere

这是我到目前为止所做的:

function check_logs{
param($logs, $logpos)
$count = 1
$path = $logs.file
$br = 0
$reader = New-Object System.IO.StreamReader("$path")
$reader.DiscardBufferedData()
$reader.BaseStream.Seek(5270, [System.IO.SeekOrigin]::Begin)
for(;;){
    $line = $reader.ReadLine()
    if($line -ne $null){$br = $br + [System.Text.Encoding]::UTF8.GetByteCount($line)}
    if($line -eq $null -and $count -eq 0){break}
    if($line -eq $null){$count = 0}
    elseif($line.Contains('Error:')){
        $l = $line.split(',')
        Write-Host "$line  $br"
    }
}

}

我还没有找到正确使用搜索功能的方法。有人能指出我正确的方向吗?

如果我运行它会输出5270,但是如果我在我试图在基本流中搜索的行中运行它,我得到:

2011-08-12 08:49:36.51 Logon       Error: 18456, Severity: 14, State: 38.  5029
2011-08-12 08:49:37.30 Logon       Error: 18456, Severity: 14, State: 38.  5270
2011-08-12 16:11:46.58 spid18s     Error: 1474, Severity: 16, State: 1.  7342
2011-08-12 16:11:46.68 spid18s     Error: 17054, Severity: 16, State: 1.  7634
2011-08-12 16:11:46.69 spid29s     Error: 1474, Severity: 16, State: 1.  7894

第一部分是从日志中读取的行,最后的数字表示在该点读取的字节数。所以你可以看到我现在正在尝试使用seek函数来跳过第一个错误行,但正如我之前所说的,如果我使用seek函数,则输出为5270。

我错过了什么?????

吉斯利

3 个答案:

答案 0 :(得分:2)

你可能能够用一些.net对象等来做这件事......

如果它是更标准的格式化日志文件,我看起来并不过logparser。它在时间之前很棒,仍然很棒!

您可以通过命令行使用它或使用PowerShell使用COM。它能够标记文件中的位置并从那里拾取(将信息存储在lpc文件中)。

可能有人会想出一个很好的方法,但如果没有,你也可以看一下切换到向事件查看器写入错误信息。您可以存储最后一个ID或上次搜索事件查看器,并每次都从那里进行检查。

希望有更好的东西......

编辑:

如果文件是制表符分隔的,则可以使用import-csv命令并存储最后一个数字(如果计数中包含标题,则它可以是count或count-1)。使用最后一个数字,您可以跳转到文件中的最后一个

# use Import-CliXML to get the $last_count
Import-CliXML $path_to_last_count_xml
$file = Import-Csv filename -delimiter "`t"
for ($i=$last_count; $i -gte $file.count; $i++) {
    $line = $file[$i]
    # do something with $line
    ...
}
$last_count = $file.count | Export-CliXML $path_to_last_count_xml

# use this to clear the memory
Remove-Variable $file
[GC]::collect

或者您可以使用sp_readerrorlog直接查询数据库;使用上次最后一次计数。

答案 1 :(得分:1)

如果您的目标是仅读取之前运行中读取的最后一行的文件请随意忽略此答案。但是,如果您只是在上次检查时间后尝试获取任何错误,这可能会有所帮助。


[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO')  | Out-Null
$server = 'ServerName'
$chkDate = Get-Date -Date '8/16/2011 15:00'  # time of last check
$srvObj =  New-Object -TypeName Microsoft.SqlServer.Management.Smo.Server -argumentList $srv
$srvObj.ReadErrorLog(0) | foreach { if ($_.LogDate -notlike '' `
   -and $_.LogDate -ge $chkDate `
   -and $_.Text -like 'Error: *') {$_}} |ft -AutoSize

如果您从文件中获取最后一次运行时间,或者只是知道每小时运行一次或其他什么,您可以调整$ chkDate以仅显示从那时到文件末尾的错误。

(注意$ srvObj.ReadErrorLog(0)行和下一行末尾的那些反向标记(`)。它们并不总是出现在我的HTML)

答案 2 :(得分:0)

如果您真的想使用PowerShell,我建议有两种选择。

  1. 使用.NET文件API。

  2. 阅读日志的全部内容,然后将其清除。将解析的内容存储在数据库中。