2011-08-11 58 views
5

我有一個用於監視數據庫的perl腳本,我試圖將它作爲powershell腳本編寫。使日誌讀取效率更高

在perl腳本中有一個函數,它讀取錯誤日誌,並過濾掉它重要的內容並將其返回。它還保存日誌文件的當前位置,以便下一次必須讀取日誌時,它可以從它離開的地方開始,而不是再次讀取整個日誌。這是通過使用告訴函數完成的。

我有一個想法,使用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。

我在想什麼?????

吉斯利

+0

提及[tell](http://perldoc.perl.org/functions/tell.html)函數+1。我以前沒聽說過。只是想知道,你是否期望重寫腳本比安裝Perl更簡單或者是否存在需求問題? –

+0

重寫是地獄,如果這就是你問的。問題是我們監控其他數據庫,這將使未來在新的Windows服務器上更容易設置。我還應該提到,今年夏天我是一名實習生,這個項目也是一種讓我學習代碼並理解腳本做什麼的方法。他們還希望有人開始學習PowerShell。簡而言之,安裝perl並使用該腳本可能會更容易。 – Gisli

+0

不太清楚你現在要求什麼 - 我會再次閱讀,但檢查你的變量 - $ l是分裂的回報,但你正在寫$ line - 你的意思是? – Matt

回答

2

你可能會能夠與一些.NET對象等做到這一點...

如果它是一個更標準格式的日誌文件,我不看過去很多雖然logparser。這真是太棒了,而且還是很棒!

您可以通過命令行或COM與PowerShell使用它。它有能力標記它在文件中的位置並從那裏拿起(將信息存儲在lpc文件中)。

可能有人會想出一個這樣做的好方法,但如果沒有,你也可以看看切換到錯誤信息寫入事件查看器。您可以存儲最後一個ID或上次搜索事件查看器並每次從那裏查看。

希望有更好的東西...

編輯:

如果文件是製表符分隔,你可以使用進口CSV命令和存儲的最後一個號碼(它會要麼被計數,或者如果頭被包含在計數計數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直接查詢數據庫;使用最後一次像上面的最後一次計數。

+0

謝謝。如果我理解正確,logparser是我需要下載和安裝的工具。腳本在powershell中重寫的原因是,我們不必在我們正在監視的新的Windows服務器上安裝perl。所以即使這是一個好工具,我們也可以在機器上安裝perl並跳過重寫。無論如何感謝 – Gisli

+0

是的它是...你的日誌文件是什麼格式? – Matt

+0

這是MSSQL服務器創建的錯誤日誌。這是一個沒有擴展名的純文本文件(文件類型'文件') – Gisli

0

如果您真想使用PowerShell,我會建議兩種選擇。

  1. 使用.NET文件API。

  2. 讀取日誌的全部內容,然後清除它。將解析的內容存儲在數據庫中。

+0

之前先導入整個文件,感謝提示。我會明天看看 – Gisli

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)

+0

感謝您的回覆。目標是隻讀取文件。但是,您是否有鏈接,以便我可以詳細瞭解您正在使用的功能。像ReadErrorLog,LogDate,Text。在這一點上,我擔心你的代碼對我來說有點複雜,但我想理解它。 – Gisli

+0

您可能會從這篇文章中獲得一些內容,您好,腳本專家http://blogs.technet.com/b/heyscriptingguy/archive/2011/05/31/use-powershell-to-get-the-sql-server- error-log.aspx SMO版本幾乎在頁面的底部。還有一個從MSDN的Microsoft.SQLServer.SMO .NET Framework的Server類的鏈接。 – Bruce