【问题标题】:Make log reading efficient让日志阅读更高效
【发布时间】:2011-10-25 01:03:27
【问题描述】:

我有一个用于监视数据库的 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"
    }
}

}

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

如果我运行它,它会输出 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。

我错过了什么??????

吉斯利

【问题讨论】:

  • +1 用于提及 tell 函数。我以前没听说过。只是想知道,您是否认为重写脚本比安装 Perl 更容易,还是涉及到需求问题?
  • 如果这就是你所要求的,那么重写就是地狱。问题是我们监视其他人的数据库,这将使将来在新的 Windows 服务器上的设置更容易。我还应该提到,今年夏天我是一名实习生,这个项目也是让我学习代码并了解脚本在做什么的一种方式。他们还希望有人开始学习 powershell。所以简而言之,安装 perl 并使用该脚本可能会更容易。
  • 目前不太确定您要的是什么-我会再读一次,但请检查您的变量-$l 是拆分的返回,但您正在编写 $line-您的意思是那个?

标签: .net perl scripting powershell


【解决方案1】:

你可能可以用一些 .net 对象等来做到这一点......

如果它是一个更标准格式的日志文件,我不会看太多过去的logparser。它在时间之前很棒,现在仍然很棒!

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

可能有人会想出一个很好的方法来做到这一点,但如果没有,您也可以考虑切换到将错误信息写入事件查看器。您可以存储最后一个 id 或上次搜索事件查看器的时间,并每次从那里检查。

希望有更好的...

编辑:

如果文件是制表符分隔的,您可以使用 import-csv 命令并存储最后一个数字(如果标题包含在 count 中,它会是 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 直接查询数据库;使用最后一次,如上面的最后一次计数。

【讨论】:

  • 谢谢。如果我理解正确,logparser 是我需要下载和安装的工具。在 powershell 中重写脚本的原因是我们不必在我们正在监视的新 Windows 服务器上安装 perl。因此,即使这是一个很好的工具,我们也可以在机器上安装 perl 并跳过重写。还是谢谢
  • 这是 MSSQL 服务器创建的错误日志。这是一个没有扩展名的纯文本文件(文件类型'file')
  • 我认为文件是制表符分隔的,所以我添加了一些代码来执行此操作,您也可以始终将循环用于普通文本文件(使用 Get-Content)来加载文件。
  • 谢谢,这可能是我可以使用的东西。我正在努力,我会通知你
  • 这可行,但是当文件变大时速度很慢,因为 Import-Csv 在搜索之前会导入整个文件
【解决方案2】:

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

  1. 使用 .NET 文件 API。

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

【讨论】:

    【解决方案3】:

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

    
    [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)

    【讨论】:

    • 感谢您的回复。目标是只读取文件。但是你有一个链接,以便我可以阅读更多关于你正在使用的功能的信息。像 ReadErrorLog、LogDate、Text。恐怕你的代码在这一点上对我来说有点复杂,但我想理解它。
    • 您可能会从这篇文章中得到一些东西,您好,脚本专家blogs.technet.com/b/heyscriptingguy/archive/2011/05/31/… SMO 版本几乎位于页面底部。 MSDN 上的 Microsoft.SQLServer.SMO .NET Framework 中还有一个指向 Server 类的链接。
    猜你喜欢
    • 1970-01-01
    • 2019-04-25
    • 2011-04-16
    • 2018-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-14
    • 2018-07-09
    相关资源
    最近更新 更多