最乾淨的解決方案是inotify的在許多方面 - 這是或多或少正是它的預期,畢竟。如果日誌文件變化非常快,那麼您可能會幾乎經常被喚醒,這並不一定非常有效 - 但是,您可以通過在inotify文件句柄返回事件後添加自己的短暫延遲來緩解此問題。在實踐中,我懷疑這在大多數系統上都會成爲問題,但我認爲值得一提的是,如果系統對CPU資源非常緊張。
我看不到sleep()
方法會錯過文件更新,除非文件被截斷或旋轉(即重命名並創建了同名文件)。這些都是棘手的情況下處理,但是你做的事情,你可以使用技巧,如定期重新打開文件的名稱來檢查旋轉。閱讀tail
手冊頁是因爲它處理了很多這樣的情況,特別是對於日誌文件而言它們非常常見(日誌輪轉被廣泛認爲是良好實踐)。
sleep()
的缺點當然是你最終會在你的閱讀過程中加入延遲,而且即使它沒有改變,你也有不斷喚醒和輪詢文件的開銷。但是,如果你這樣做了,比如每秒一次,那麼在大多數系統上,開銷可能並不明顯。
我想說的inotify是最好的選擇,除非你想保持兼容,在這種情況下使用sleep()
簡單的後備還是相當合理的。
編輯:
我才意識到我忘了提 - 一種簡單的方法來檢查被重命名的文件被執行在打開的文件句柄,你開設了一個os.fstat(fd.fileno())
並在文件名os.stat()
和比較結果。如果那麼os.stat()
失敗的錯誤會告訴你,如果該文件被刪除了,如果沒有的話比較st_ino
(inode編號)字段將告訴你,如果該文件被刪除了,然後用相同名稱的更換成新的。
檢測截斷更難 - 有效地將讀指針保持在相同的文件,並讀取偏移將返回什麼,直到文件內容尺寸變回你在哪裏 - 那麼該文件將從該點爲正常讀取。如果您經常撥打os.stat()
,則可以檢查文件大小是否倒退 - 或者,您可以使用fd.tell()
在文件中記錄當前位置,然後對文件末尾執行明確搜索並再次調用fd.tell()
。如果該值較低,則該文件已被截斷。只要您保持原始文件位置,這是安全的操作,因爲您可以在檢查之後始終尋找它。
另外,如果你使用inotify,你可以只看父目錄的變化。
請注意,文件可以被截斷爲非零大小,但我懷疑這可能發生在日誌文件 - 常見情況將被刪除和替換,或截斷爲零。另外,我不知道如何檢測文件被截斷的情況,然後立即填充回到當前位置以外的位置,除非記住最近的N個字符並對它們進行比較,但這是一個非常糟糕的事情做。我認爲inotify只會告訴你在這種情況下文件已被修改。
GNU尾部實現 - http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/tail.c搜索「inotify」,他們似乎使用它(如果可用)。 – Dogbert
注意第三個可能的答案:'popen = subprocess.Popen([「tail」,「-f」,filename])''。然後在您的框架中使用popen.stdout上的常規管道讀取方法,對此您可能已經有了支持。 –