2010-06-28 35 views
0

我開發一個腳本來閱讀和搜索日誌文件在工作中的大系統。 它目前是這樣工作的:閱讀活動日誌文件,而不需要一個臨時文件

  1. 用戶定義的搜索參數
  2. PHP使用了shell_exec(「TAC LOGFILE.LOG> tmpfile.log」)來複制日誌文件(和反向線)到一個臨時文件
  3. PHP fopen()函數的臨時文件
  4. PHP讀取通過文件的每一行,並應用搜索參數
  5. PHP刪除#做出的臨時文件2

我決定採用這種方法,因爲日誌文件每隔幾秒就寫入一次,我需要向後讀取日誌文件。

我的問題是,第2步需要很長的時間,當日志文件> 300MB,並且每天的日誌文件很容易500MB,所以搜索這麼多的數據實在是費時。

我有幾個問題:)上的活動日誌文件

  1. 我可以簡單地運行的fopen(?
  2. 它可能會導致日誌文件的損壞,如果我只是讀它,而其他腳本編寫呢?
  3. 將它減慢腳本寫入日誌文件,如果我在同一時間讀它?
  4. 我可以讓PHP讀取文件的每一行而不是轉發嗎?

我希望是有道理的......

回答

2

要回答的編號問題:

在Unix或Unix類系統:

1:隨意fopen()函數任何你想要的。附加到文件的其他進程不會被搞砸。移動文件的其他過程不會被搞砸。其他進程刪除文件不會被搞砸。他們的業務將繼續取得成功,您的業務也會如此。

2:讀取文件不會阻止寫作的作家,除非文件系統適用強制性文件鎖定。這是不太可能的,因爲這是一個巨大的性能損失。 (有關強制鎖定的詳細信息,請參閱系統的fcntl(2)聯機幫助頁。)

3:在讀取文件時,寫入日誌的腳本可能不會運行得更慢。文件數據和元數據需要被寫入或讀入內存中;如果您的搜索將緩存保持爲熱點,則日誌記錄甚至可以運行(稍微快一點)。

4:沒有線索。 :)

我能想到的幾種可能的方法來解決這個問題:

首先,你可以先執行搜索和然後扭轉結果:

grep danger /var/log/messages | tac 

搜索將不假設你的結果是一個足夠小的整體的子集,那麼走得更快,但是會倒退。其次,你可以使用dd(1)的skip = BLOCKS參數定期將你的日誌文件分割成幾部分;通過將文件分成10兆字節塊,將倒轉一次,並且每次重新處理剩餘的部分,您可以分攤全天倒置文件的成本。正確編程需要更多努力,但節省時間可能是值得的。這取決於需要多長時間查詢一次。第三,你可以編寫你自己的道德等價物tail(1)-f,它將每個新行填充到環形緩衝區文件中。您將會覆蓋之前的行,但聽起來您的日誌輪轉已經限制了返回的數據量。 600兆字節的限制可能是合理的。您的查詢可能以最近寫入的字節開始,直到文件末尾,然後在文件的開頭重新開始,如果沒有返回足夠的結果。這可能需要盡最大的努力才能得到正確的結果,但是可以通過每次寫入日誌來分攤反轉數據庫的成本。 (如果寫入日誌的腳本是突發性的,則這可能會嚴重地與高峯使用時的磁盤帶寬劇本競爭。)

+0

真棒,感謝您回答我的問題:) 使用grep是我想到的一種可能性,但我的搜索很複雜,我還沒有查看過grep搜索的具體情況。 我正在考慮自動反轉所有日誌文件的順序欄中活動的一個。它應該使搜索檔案更快。 – 2010-06-28 10:38:02

1

由於您使用shell_exec已經你可能想在它使用tail

用法:尾[選項] ... [FILE ] ...
將每個FILE的最後10行打印到標準輸出。 對於多個FILE,每個FILE前面都有一個標題給出文件名。 沒有FILE,或者當FILE是 - 時,讀取標準輸入。

+0

+1因爲提問者不要求提供僅限PHP的解決方案。在PHP中重新實現'tail'並不難,但在這裏會過度。不過,我想知道他是否真的只想要尾巴。好像他想要搜索整個文件,只是相反。 – janmoesen 2010-06-28 07:07:28

+0

感謝您的解決方案,但我正在搜索整個文件。我想反過來,因爲我限制了比賽的數量,我希望最先找到最新的比賽。 – 2010-06-28 10:34:30

+0

@janmoesen是的,我沒有正確閱讀@ Valorin的問題。仍然可以使用'grep'然後,然後像[由sarnold下面提示](http://stackoverflow.com/questions/3130358/read-active-log-files-without-needing-a-temp-file/3130999# 3130999) – Gordon 2010-06-28 10:44:06