1. 程式人生 > >遇到一個日誌檔案變化帶來的檔案控制代碼問題

遇到一個日誌檔案變化帶來的檔案控制代碼問題

正在進行的專案中有個系統除錯日誌儲存的功能,需要儲存列印資訊。測試部反饋了一個bug:除錯日誌檔案有時候不更新。對照程式碼,專案用的程式碼和之前專案的程式碼是一樣的。感覺沒什麼問題,我自己測試沒發現有不更新的情況,但測試部已經反饋過幾次了,肯定有問題。專案deadline很快到了(按計劃,應該是本文發表前4天已經是deadline了),——也正因為如此,開始了本年第一次週末加班。專案經理不放過這個問題,經分析程式碼,最終算是解決了問題。

事情起因於linux的syslog日誌服務和我們所採用的日誌分析機制。我們通過syslog函式將日誌存放到syslog服務指定的檔案(通過配置檔案來指定,如/var/log/syslog),人為地規定日誌等級,就可以從中分析這些日誌來分門別類儲存。以前所有的專案,linux系統都是基於記憶體的ramdisk,一旦斷電,系統產生的東西將不復存在。雖然有專案使用了nand flash,但鑑於技術掌握的問題,還是採用記憶體系統。當時,linux根檔案系統使用busybox來構建,很多工具和服務無法和桌面版如ubuntu/fedora匹敵,也正因為如此,系統級別的工具都是針對某一特定功能來移植、剪裁,比如syslog。

上面提到的問題,其實一開始已經遇到了,當時我對syslog配置沒什麼研究——我根本就不能接觸核心和根檔案系統這一塊,負責上層應用程式的日誌模組的同事說有問題,在某個時刻就不能從syslog檔案講到資料了,因為開啟該檔案的控制代碼無效了。我查了發現儲存的日誌容量達到10MB後就會備份,原來的檔案會被改名甚至壓縮來備份。雖然表面上檔名稱不變,但檔案已經變化了,控制代碼自然無效。後來我查到可以通過引數將syslog檔案回滾,始終保持一個檔案。這樣解決了控制代碼問題,鑑於使用記憶體系統,這樣做也沒問題。當時我沒有接觸上層應用程式,不知他們已經在程式碼中解決控制代碼問題(用stat函式來讀取並判斷新舊檔案節點是否一致)。那時我所在的負責linux底層的部門,要不斷適應應用程式不好解決的問題,通過修改系統來適應。

後來日誌模組使用了新的技術,使用通道函式popen來開啟查詢日誌的命令(但沒有對檔案控制代碼作判斷),當然,系統級別的syslog配置還是和以前一樣。

這個專案中的很多東西和以前不一樣,在專案初期沒人去評估。我一來被bios和構建適合的系統等事情煩擾,二來本著不在其位不謀其政的態度,對此問題沒有過多關注,現在來看,最終的苦果扔給了自己。由於使用了較大容量的硬碟作為儲存介質,不再像之前用flash介質那樣能省就省。我直接使用ubuntu作為系統的基本版本加上自定義的剪裁,而日誌服務,變成了強大的rsyslogd,經過配置,在儲存日誌體積和時間上達到我認為的平衡點,既不佔用太多的硬碟,也能儲存約10天的日誌資訊(對於運維來說,資訊實在太可憐了)。因為linux系統中用syslog來記錄、備份日誌是十分正常的事,我也以為其它同事也此認識。

但我還是沒有意識到那個控制代碼的問題:因為程式碼沿用以前的,而日誌檔案機制變化了。於是,測試人員發現這個bug。這個還是專案經理告訴我的,我對公司的架構還不十分熟悉,很多模組沒什麼文件,之前還有遇到一個問題是因為別人把本該用冒號的地方用逗號而找了好幾天,這類的坑,讓新手很鬱悶。

在保留日誌模組用新的方式下修改,發現會影響其它的日誌小模組,幾經測試,發現不成功,於是改用回舊的方法,經過幾次測試,發現沒問題,算是解決了。

各有各的錯,應用程式人員不應太依賴不變的系統,總想著不動程式碼,系統自然會適應,大部分人不會讓日誌資訊只存在一個相同的檔案而不進行備份的。系統人員不應不瞭解上層使用而改動某些機制。前者讓人覺得換了一個平臺上層程式碼又得改,不符合架構的設計本意;後者覺得不更改,就會固步自封,不能進步。總之,各有各的理,用之前和同事爭吵時的話來說:讓英明的領導來決斷吧。

1.26 週一 PS:

上班時,對這個問題還是不死心,繼續研究。程式碼使用了tail -f來讀取日誌檔案末尾的內容,看了下tail的用法,選項有-f和-F。-F表示“-F     same as --follow=name --retry”,因為有retry,會保證檔案變化了,繼續跟蹤內容。當日志文件因為時間或容量到達rotate時,也不怕內容丟失了。

因此,本文遇到的問題,將程式碼的“-f”改為“-F”即可解決。——又是一個只改動個別字元就解決的bug。當時思路沒開啟,沒往這個方向走,浪費了不少時間。

李遲 2015年1月25日 週日 下午