文章目錄
一、前言
python
通過fllow
讀取文件,需求是可以監控log
文件,當文件行數增加的話,就寫入到數據庫,也可以讀取歷史log
文件,寫入到數據庫,因此我們通過給腳本添加參數的方式來區分是否監控log
文件。
可是當執行python
的時候,明明log
文件沒有新增數據,但是發現每隔60s
,python
就會讀取log
文件的舊數據,並插入到數據庫。這當然是不符合需求的,正常來說,log
文件無變化,fllow
不應該再去讀取文件纔對。
二、讀取fllow源碼
遇到文件就讀源碼,碼中自有黃金屋,碼中自有顏如玉。
1、fllow讀取文件代碼
thefile = follow.Follow(filename, False)
fllow的Follow函數如下:
class Follow(object):
def __init__(self, fname, start=False, new_file_check=60, *open_args):
可以看到參數中有個new_file_check =60,這個參數會不會就是罪魁禍首呢?
2、跟蹤new_file_check 函數
def _preread(self):
if not self.f:
self._reopen(False)
return
t = time.time()
if t >= self.stat_time + self.stat_time_min: # 這部分用到了
nstat = os.stat(self.fname)
self.stat_time = t
if nstat.st_dev != self.stat.st_dev or \
nstat.st_ino != self.stat.st_ino:
# start at top of new file
self._reopen(True)
return
# should clear previous EOF condition
self.f.seek(self.pos)
代碼的語意是:
當60s
之後,腳本會重新獲取文件的相關屬性,並對比文件的相關參數,若參數不一致則重新讀取文件。
看來問題就出在了這個對比屬性上,下面先看看這些屬性都是什麼意思
3、python的stat函數
根據if條件左邊的代碼格式,我們知道是用os.stat()函數的返回值進行對比的。
根據if條件右邊的代碼格式,我們可追蹤代碼,最終鎖定在os.fstat()函數
手冊解析:
https://www.runoob.com/python/os-stat.html
os.stat()
方法用於在給定的路徑上執行一個系統 stat
的調用。
https://www.runoob.com/python/os-fstat.html
os.fstat()
方法用於返回文件描述符fd
的狀態,類似 stat()
。Unix,Windows
上可用。
根據這個教程,我們發現
os.stat返回的結果有:
st_mode: inode 保護模式
st_ino: inode 節點號。
st_dev: inode 駐留的設備。
st_nlink: inode 的鏈接數。 等
os.fstat返回的結果有:
st_dev: 設備信息
st_ino: 文件的i-node值
4、分析出錯代碼
if nstat.st_dev != self.stat.st_dev or \
nstat.st_ino != self.stat.st_ino:
# start at top of new file
self._reopen(True)
return
首先是對比: inode 駐留的設備 != 設備信息
其次是對比:inode 節點號 != 文件的i-node值
兩次對比有一次不同則重新讀取文件,也就是造成我們上面的bug
。
三、windows下對比inode 節點號
1、windows下打印這幾個參數
print nstat.st_dev
print self.stat.st_dev
print nstat.st_ino
print self.stat.st_ino
結果:
0
0
0
73746443898579758
OK
,根據結果已經知道是文件的inode
值不同,所以造成了重新讀取文件的bug
。那麼爲什麼文件屬性會發生變化呢,本地數據量又沒有增加。而且既然這個文件是常用的讀取文件腳本,那麼怎麼可能會有這明顯的bug
2、os.start() 與 os.fstat()
首先明確一點,兩個函數都能在windows
下正常運行。函數含義也有些相似,唯一不一樣的一點就是inode
的值,關於inode
,聽說最多的就是linux
文件系統的inode
了,那麼會不會是windows
下的inode
和linux
的inode
不一樣,或者windows
不夠穩定呢
3、linux文件的inode會保持不變嗎?
答案:
inode
在文件的生命週期裏是不改變的,除非,你把文件刪除重建。而你刪除文件前100
行的動作,實際上是新建一個臨時文件,把舊文件第100
行以後的東西輸出到臨時文件裏,刪掉舊文件,把臨時文件的文件名重命名成舊文件的名字。也就是說你刪前100
行的時候,文件已經經歷了刪除-重建的過程,inode
號也就改變了。
作者:北極
鏈接:https://www.zhihu.com/question/26127845/answer/32214159
來源:知乎
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。
4、windows文件的inode會保持不變嗎?
通過搜索我們發現,對於windows
來說,它有類似於inode
的概念,比如通過卷序列號/ FileId組合等來標識目錄文件,但是windows
下並沒有直接的inode
概念,所以在windows
下通過inode
對比文件是不穩定且不精準的。
關於windows的inode,有興趣的可以參考:
http://zgserver.com/windowsinode.html
http://cn.voidcc.com/question/p-nvmqdzhb-vo.html
這樣一對比,答案就很明顯了,windows
下問題奇葩問題多,怪不得大佬們都用mac
電腦開發呢,大佬們果然誠不我欺。
四、解決方案
通過以上的分析,可以知道這個鍋算是windows
的鍋,怪不得py
腳本在windows
下那麼多的bug
,因爲windows
和linux
在某些函數調用上還是有一些差距的,建議是到linux
服務器上跑一跑看看。
因此上傳py
腳本到linux
,在linux
上測試,發現完美實現監控日誌文件的目的,文件有更新則寫入到數據庫,無更新則持續讀取。
五、總結
通過這篇文章的分析,對博主對打的觸動就是:windows環境果然是坑。 怪不得大佬們都是用mac
電腦,天天在linux
下開發呢,博主本來在windows
下開發php
開發的不亦樂乎,只可惜以後始終是要用到編譯型語言的,早晚都要完全在linux
下開發啊。。
行吧,解決問題的過程永遠是複雜的,查找的過程永遠是享受,通過這個問題博主又學到了很多python
的知識,整體來說還是很讚的。
我是鐵柱,我爲自己代言!
end