Сделайте чтение журнала эффективным - PullRequest
5 голосов
/ 11 августа 2011

У меня есть сценарий perl, который используется для мониторинга баз данных, и я пытаюсь написать его как скрипт powershell.

В скрипте perl есть функция, которая читает журнал ошибок, отфильтровывает, что это имеет значение, и возвращает его обратно.Он также сохраняет текущую позицию файла журнала, так что в следующий раз, когда ему нужно будет прочитать журнал, он может начать с того места, где он ушел, вместо того, чтобы снова читать весь журнал.Это делается с помощью функции tell .

У меня есть идея использовать командлет Get-Content и начать чтение с последней позиции, обрабатывать каждую строку до конца файлаи затем сохраняя позицию.

Знаете ли вы какие-либо приемы, чтобы я мог получить позицию в файле журнала после чтения и начать чтение в определенном месте.

Или есть лилучший и / или более простой способ добиться этого?

Gísli

РЕДАКТИРОВАТЬ: Это должно быть сделано с помощью сценария, а не с каким-либо другим инструментом.

РЕДАКТИРОВАТЬ: Итак, я где-то с .NET API, но это не совсем работает для меня.Я нашел полезные ссылки здесь и здесь

Вот что у меня есть:

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

Где первая часть - это строка, прочитанная из журнала, а число в конце представляет байты, прочитанные в этой точке.Итак, как вы можете видеть, я сейчас пытаюсь использовать функцию поиска, чтобы пропустить первую строку ошибки, но, как я сказал ранее, на выходе будет 5270, если я использую функцию поиска.

Чего мне не хватает ?????

Gísli

Ответы [ 3 ]

2 голосов
/ 11 августа 2011

вы, вероятно, сможете сделать это с некоторыми объектами .net и т. Д. *

Если это более стандартный отформатированный файл журнала, я не слишком далеко захожу logparser . Это было потрясающе раньше времени и все еще потрясающе!

Вы можете использовать его через командную строку или COM с PowerShell. У него есть возможность пометить, где он был в файле и получить оттуда (информация хранится в файле lpc).

Может быть, кто-то придумает хороший способ сделать это, но если нет, вы также можете посмотреть на переключение на запись информации об ошибках в просмотрщик событий. Вы можете сохранить последний идентификатор или последний раз, когда вы искали средство просмотра событий, и проверять оттуда каждый раз.

Надеюсь, что-то лучше ...

РЕДАКТИРОВАТЬ:

Если файл разделен табуляцией, вы можете использовать команду import-csv и сохранить последнее число (это будет либо count, либо count-1, если заголовок включен в count). С помощью последнего номера вы можете перейти к последней точке в файле

# 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 голос
/ 17 августа 2011

Если ваша цель - прочитать файл только из последней строки, прочитанной в предыдущем запуске, пожалуйста, не стесняйтесь игнорировать этот ответ.Однако, если вы просто пытаетесь получить какие-либо ошибки с момента последней проверки, это может помочь.


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

0 голосов
/ 11 августа 2011

Я бы предложил два варианта, если вы действительно хотите использовать PowerShell.

  1. Использовать файловые API .NET.

  2. Прочитайте все содержимое журнала, а затем очистите его.Сохраните проанализированное содержимое в базе данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...