日常前言
最開始建站的時候,網上搜集怎麼對nginx產生的日誌進行按小時切斷的方法,搜出來的基本都是使用sh的腳本(Linux能直接解析的語言),無法完全看懂的我只好直接ctrlCV(T_T)。
後來想想,幹嘛不用Python試試呢?說寫就寫!
開始
第一步,按時截斷
按時
一般來說我們都是不會希望巨多的日誌數據全部存儲到一個文件裏的,所以我們需要按自己的需要進行定時截斷日誌。
在實際生產過程中,在服務上while True
跑一個py腳本是不現實的,這裏通過一個名爲crond的包來實現定時任務(內置的,沒有就yum安一下)。我們通過crontab -e
來編輯其內容,他的格式爲分 時 日 月 星期 執行腳本的解釋器 執行的文件
。比如每小時運行一次的方法就是0 * * * * /usr/bin/python /opt/sbin/cut_nginx_logs.py
在多給幾個實例方便使用
*/5 * * * * 每五分鐘執行
0 * * * * 每小時
0 0 * * * 每天
0 0 * * 0 每週
0 0 1 * * 每月
0 0 1 1 * 每年
注意:每一次修改都需要重啓crond服務!
截斷:
這個接比較簡單了,直接使用os.system
配合linux的mv
命令就可以實現效果
第二步:清空size爲0的日誌
肯定有人要問了,爲什麼需要size爲0的文件呢?我可以保證我的網站每小時都能產生巨多的訪問流量,每一個訪問日誌都不會空下來。
- 第一:萬一哪個產品經理就是要讓你這麼做呢?(手動滑稽)
- 第二:就算訪問量巨多,每個訪問文件都爆滿,有沒有想過錯誤記錄文件的數量呢?當網站的後端代碼部署到服務器上之後,我們一般都會開啓
DEBUG = False
這個選項,更多時間會選擇在本地進行bug調試,而服務器上的錯誤日誌記錄只會在本地環境無法測試的時候纔會去看,從產生大量size爲0的環境,如下圖:
So,說通了理由,再來說說他的實現思路。通過os.listdir
先獲取到指定目錄下所有的日誌文件名(返回的是一個數組),然後使用os.path.getsize
獲取到文件的大小(單位:字節),最後使用if
配置os.remove
進行一套組合拳完成需求
def empty(self):
'''清空size爲0的日誌'''
self._sizeA = os.listdir(self.access_dir)
self._sizeE = os.listdir(self.error_dir)
for i in self.sizeA:
if os.path.getsize(self.access_dir + i) == 0:
os.remove(i)
for i in self.sizeE:
if os.path.getsize(self.error_dir + i) == 0:
os.remove(i)
最後:每月清空一次所有日誌
這個比較簡單了,也不需要去寫什麼contab -e
(跟在按時截斷文件裏進行判斷時間即可)
def rm(self):
'''每個月的第一天刪除所有的日誌'''
self._rm1 = 'rm -rf /opt/logs/access/*'
self._rm2 = 'rm -rf /opt/logs/error/*'
os.system(self._rm1)
os.system(self._rm2)
最後
在我看來,大多數能想得到的功能,一旦用Python來實現,那百分之九十都是既優雅又簡潔。最後的最後附上源代碼。
import os
import time
class Logs(object):
"""docstring for Logs"""
def __init__(self):
self.__now_time = time.strftime('%m%d%H-%Y', time.localtime(time.time()))
self.__access_dir = '/opt/logs/access/'
self.__error_dir = '/opt/logs/error/'
def cut(self):
'''剪切日誌'''
self._Acommod = 'mv %saccess.log %s%s.log' % (self.__access_dir,self.__access_dir,self.__now_time)
self._Ecommod = 'mv %serror.log %s%s.log' % (self.__error_dir,self.__error_dir,self.__now_time)
os.system(self._Acommod)
os.system(self._Ecommod)
os.system('systemctl reload nginx')
def empty(self):
'''清空size爲0的日誌'''
self._sizeA = os.listdir(self.__access_dir)
self._sizeE = os.listdir(self.__error_dir)
for i in self._sizeA:
if os.path.getsize(self.__access_dir + i) == 0:
os.remove(i)
for i in self._sizeE:
if os.path.getsize(self.__error_dir + i) == 0:
os.remove(i)
def rm(self):
'''每個月的第一天刪除所有的日誌'''
self._rm1 = 'rm -rf /opt/logs/access/*'
self._rm2 = 'rm -rf /opt/logs/error/*'
os.system(self._rm1)
os.system(self._rm2)
Logs().cut()
h = time.strftime('%H', time.localtime(time.time()))
d = time.strftime('%d', time.localtime(time.time()))
if h == 00:
Logs().empty()
if d == 01:
Logs().rm()