多伺服器的日誌合并統計(2)
來源:互聯網
上載者:User
伺服器|統計 比較簡便不影響服務的方法是:先複製,後清空
cp /path/to/apache/log/access_log /path/to/apache/log/access_log_yesterday
echo >/path/to/apache/log/access_log
嚴肅的分析員會這樣做發現一個問題:
但cp不可能嚴格保證嚴格的0點截斷。加入複製過程用了6秒,截斷的access_log_yesterday日誌中會出現複製過程到00:00:06期間的日誌。對於單個日誌統計這些每天多出來幾百行日誌是沒有問題的。但對於多個日誌在跨月的1天會有一個合并的排序問題:
[31/Mar/2002:59:59:59 +0800]
[31/Mar/2002:23:59:59 +0800]
[01/Apr/2002:00:00:00 +0800]
[01/Apr/2002:00:00:00 +0800]
要知道[01/Apr/2002:00:00:00 這個欄位是不可以進行"跨天排序"的。因為日期中使用了dd/mm/yyyy,月份還是英文名,如果按照字母排序,很有可能是這樣的結果:排序導致了日誌的錯誤
[01/Apr/2002:00:00:00 +0800]
[01/Apr/2002:00:00:00 +0800]
[01/Apr/2002:00:00:00 +0800]
[01/Apr/2002:00:00:00 +0800]
[01/Apr/2002:00:00:00 +0800]
[01/Apr/2002:00:00:00 +0800]
[01/Apr/2002:00:00:00 +0800]
[31/Mar/2002:59:59:59 +0800]
[31/Mar/2002:59:59:59 +0800]
[31/Mar/2002:23:59:59 +0800]
[31/Mar/2002:59:59:59 +0800]
[31/Mar/2002:23:59:59 +0800]
這些跨天過程中的非正常資料對於webalizer等分析工具來說簡直就好像是吃了一個臭蟲一樣,啟動並執行結果是:它可能會把前一個月所有的資料都丟失!因此這樣的資料會有很多風險出現在處理上月最後一天的資料的過程中。
問題的解決有幾個思路:
1) 事後處理
所以一個事後的處理的方法是:用grep命令在每月第1天將日誌跨月的日誌去掉,比如:
grep -v "01/Apr" access_log_04_01 > access_log_new
修改SORT後的日誌:所有跨天的資料去掉。也許對日誌的事後處理是一個途徑,雖然sort命令中有對日期排序的特殊選項 -M(注意是:大寫M),可以讓指定欄位按照英文月份排序而非字母順序,但對於apache日誌來說,用SORT命令切分出月份欄位很麻煩。(我嘗試過用 "/"做分割符,並且使用"月份" "年:時間"這兩個欄位排序)。雖然用一些PERL的指令碼肯定可以實現,但最終我還是放棄了。這不符合系統管理員的設計原則:通用性。 並且你需要一直問自己:有沒有更簡單的方法呢?還有就是將日誌格式改成用TIMESTAMP(象SQUID的日誌就沒有這個問題,它的日誌本身就是使用TIMESTAMP做時間戳記的),但我無法保證所有的日誌工具都能識別你在日期這個欄位使用了特別的格式。
2) 最佳化資料來源
最好的辦法還是最佳化資料來源。將資料來源保證按天輪循,同一天的日誌中的資料都在同一天內。這樣以後你無論使用什麼工具(商業的,免費的)來分析日誌,都不會因為日誌複雜的預先處理機制受到影響。
首先可能會想到的是控制截取日誌的時間:比如嚴格從0點開始截取日誌,但在子夜前1分鐘還是後一分鐘開始截取是沒有區別的,你仍然無法控制一個日誌中有跨2天記錄的問題,而且你也無法預測日誌歸檔過程使用的時間。
因此必須要好好考慮一下使用日誌輪循工具的問題,這些日誌輪循工具要符合:
1) 不中斷WEB服務:不能停apache=>移動日誌=>重啟apache;
2) 保證同一天日誌能夠按天輪循:每天一個日誌00:00:00-23:59:59;
3) 不受apache重啟的影響:如果apache每次重啟都會產生一個新的日誌是不符合要求的;
4) 安裝配置簡單。
首先考慮了apache/bin目錄下內建的一個輪循工具:rotatelogs 這個工具基本是用來按時間或按大小控制日誌的,無法控制何時截斷和如何按天歸檔。
然後考慮logrotate後台服務:logrotate是一個專門對各種系統日誌(syslogd,mail)進行輪循的後台服務,比如SYSTEM LOG,但其配置比較複雜,放棄,實際上它也是對相應服務進程發出一個-HUP重啟命令來實現日誌的截斷歸檔的。