5

我有一个要求,到目前为止我还没有在论坛上找到解决方案或帮助...

问题:我监控实时系统,这些会生成许多非常大的日志文件,这些文件每天都会滚动,1GB 并不少见,我所做的是查看(尾端)日志以了解已知的错误情况或我想要监控的其他字符串,我可能需要对其采取行动。

由于此类工作既耗时又乏味,而且人为错误很容易遗漏日志中的问题,因此我一直在自动化此日志文件监控。我利用一个名为 Servers Alive 的产品来执行计划检查,并编写脚本来监视日志文件中是否出现我感兴趣的日志条目,这些条目可能表明服务存在问题,并且我可以在必要时调用其他脚本来重新启动服务解决遇到的问题。

我之前使用 Perl 为这些日志监控任务编写了脚本,这些脚本非常快,但不一定是最干净的方法,我是管理员而不是程序员,所以我没有开发人员方法或经验依靠。

下面的 Perl 代码片段显示我“打开”了一个日志文件$logfile,然后从文件末尾向后“寻找”给定数量的数据,然后我从该点到文件末尾搜索数据我有兴趣监控的日志条目,在这个例子中,日志条目是“ No packet received from EISEC Client

在此示例中,我们正在监视的日志条目表明 EISEC 服务存在问题,并且简单地重新启动服务通常可以解决问题,所有这些我都会自动使用 Servers Alive 作为计划的检查和警报机制。

Perl 脚本函数

sub checkEisecSrvloggedon {

print "$logfile\n";

if (open (EISECSRV_LOGGEDON, $logfile)) {

    seek (EISECSRV_LOGGEDON, -40000, 2);

    $line = <EISECSRV_LOGGEDON>;

    $eisecsrvloggedon_ok = 0;

    while ($line = <EISECSRV_LOGGEDON>) {   

            if ($line =~/No packet received from EISEC Client/) {

                #increment counter
                ++$eisecsrvloggedon_ok; 

                }

            }
        }
    }

现在我们已经转移到Windows Server 2008 R2Windows 7客户端,如果可能的话,我想为此使用 PowerShell 实现一个解决方案,但是我无法找到有关如何快速有效地执行此操作的详细信息,并且没有任何大的内存开销。

我尝试过基于 Get-Content 的解决方案,但由于需要读取整个日志文件,因此这些类型的解决方案无法使用,因为查询日志文件需要很长时间。我需要能够定期检查这些大型日志文件中的一些,在某些情况下每隔几分钟检查一次。我已经看到非常适合尾随日志文件末尾的尾部类型解决方案,并且这些脚本正在使用System.IO.File方法。这确实获得了我希望在我的脚本中实现的性能/速度,但我对PowerShell不够熟悉,不知道如何使用这种方法快速到达大型日志文件的末尾,然后能够向后读取给定数量的数据,然后在此日志部分中搜索相关字符串。

有没有人有任何想法?

4

3 回答 3

6

如果您使用 PowerShell 3.0 或更高版本,则可以结合使用get-contentselect-string命令行开关来获得相同的功能。从 3.0 版开始,get-content支持-tail仅以有效方式返回文件最后n行的选项。使用它,您可以使用以下内容重新实现上面的 Perl 脚本(在最后 1000 行中搜索):

# Returns the number of occurrences
(get-content logfile.txt -Tail 1000 | select-string -pattern "No packet received from EISEC Client").Length
于 2012-11-29T11:40:19.707 回答
2

向后寻求,对 Poshcode 存储库的贡献似乎非常符合您的要求:

# Name: Get-Tail.ps1
# Author: William Stacey
# Created: 02/22/2007
# Description: Gets the last N lines of a file. Does scan from end-of-file so works on large files. Also has a loop flag that prompts for refresh.

function Get-Tail([string]$path = $(throw "Path name must be specified."), [int]$count = 10, [bool]$loop = $false)
{
    if ( $count -lt 1 ) {$(throw "Count must be greater than 1.")}
    function get-last
    {
        $lineCount = 0
        $reader = new-object -typename System.IO.StreamReader -argumentlist $path, $true
        [long]$pos = $reader.BaseStream.Length - 1

        while($pos -gt 0)
        {
            $reader.BaseStream.Position = $pos
            if ($reader.BaseStream.ReadByte() -eq 10)
            {
                if($pos -eq $reader.BaseStream.Length - 1)
                {
                    $count++
                }
                $lineCount++
                if ($lineCount -ge $count) { break }
            }
            $pos--
        } 

        if ($lineCount -lt $count)
        {
            $reader.BaseStream.Position = 0
        }

        while($line = $reader.ReadLine())
        {
            $lines += ,$line
        }

        $reader.Close()
        $lines
    }

    while(1)
    {
        get-last
        if ( ! $loop ) { break }
        $in = read-host -prompt "Hit [Enter] to tail again or Ctrl-C to exit"
    }
}
于 2012-11-29T11:46:34.757 回答
1

PSCX有一个名为的 cmdlet Get-FileTail,它可以有效地获取文件的最后一行,从而避免事先读取完整的文件。

于 2012-11-29T11:39:33.023 回答