2009-02-10 49 views
4

我最近想出了一種情況,我需要修剪一些相當大的日誌文件,一旦它們超過一定的大小。除了每個文件中最後1000行的所有內容都被丟棄之外,該作業每隔半小時由cron運行一次。我的解決方案是簡單地遍歷文件列表,檢查大小並在必要時修剪。如何使用Perl修整日誌文件?

for $file (@fileList) { 
    if (((-s $file)/(1024 * 1024)) > $CSize) { 
     open FH, "$file" or die "Cannot open ${file}: $!\n"; 
     $lineNo = 0; 
     my @tLines; 

     while(<FH>) { 
     push @tLines, $_; 
     shift @tLines if ++$lineNo < CLLimit; 
     } 
     close FH; 

     open FH, ">$file" or die "Cannot write to ${file}: $!\n"; 
     print FH @tLines; 
     close FH; 
} 

這個工程在當前的形式,但由於需要在每一行讀取並在必要時轉向大型日誌文件大量開銷(特別是那些與100_000 +線)。

有什麼方法可以在文件的一部分中讀取,例如:在這種情況下,我想只能訪問最後的「CLLimit」行。由於該腳本正在部署在已經看到更好的日子的系統上(思考Celeron 700MHz和64MB RAM),我正在尋找使用Perl的更快的替代方案。

回答

8

我意識到你想要使用Perl,但如果這是一個UNIX系統,爲什麼不使用「tail」工具來修剪呢?你可以用一個非常簡單的腳本做在BASH:

if [ `stat -f "%z" "$file"` -gt "$MAX_FILE_SIZE" ]; then 
    tail -1000 $file > $file.tmp 
    #copy and then rm to avoid inode problems 
    cp $file.tmp $file 
    rm $file.tmp 
fi 

話雖這麼說,你可能會發現this post非常有幫助的,如果你在使用Perl此設置。

+0

感謝bash的例子,我對這個任務有類似的東西,但是我正在把所有的bash腳本轉換成Perl,所以需要一些指導。 Perl Monks教程看起來很有希望,我稍後會看看它。 – aks 2009-02-10 06:08:41

+0

即使使用unix系統,您也可以獲取其他操作系統的尾部。 :) – 2009-02-10 17:48:36

4

估計日誌中一行的平均長度 - 稱它爲N個字節。

從文件末尾向後搜索1000 * 1.10 * N(因子1.10中的誤差爲10%)。從那裏閱讀,只保留最近的1000行。


有人問 - 它的功能或模塊?

內置功能seek在我看來喜歡使用的工具?

+0

我的確在想這樣的事情,但是由於我對Perl的知識有限,我不知道用什麼模塊來完成任務。對於例如我會用什麼函數在Perl文件中向後尋找? – aks 2009-02-10 06:10:19

4

考慮簡單地使用logrotate工具;它被包含在大多數現代Linux發行版中。 BSD系統的相關工具稱爲newsyslog。這些工具的設計或多或少都是爲了您的預期目的:它原子地將日誌文件移出原位,創建一個新文件(名稱與以前相同)以保存新日誌條目,指示程序生成消息以使用新文件,然後(可選)壓縮舊文件。您可以配置保留多少個輪轉日誌。這裏有一個潛在的教程: http://www.debian-administration.org/articles/117

它不是你想要的接口(保持一定數量的行),但程序可能會比你自己做的更強大;例如,這裏的答案不涉及原子地移動文件並通知日誌程序使用新文件,因此存在某些日誌消息丟失的風險。

相關問題