浅析python 定时拆分备份 nginx 日志的方法
一、背景:
nginx的log不会自动按天备份,而且记录时间格式不统一,此程序专门解决这两个问题;
二、windows部署方式
1.在nginx目录,创建一个nginx_logs_backup.bat文件;文件内容如下
pythonnginx_logs_splter.py--nginxConf=nginx.conf--nginxDir=xxxxx--logPrefixs=access,error
2.在定时任务中加一个定时任务,调用这个bat文件;
2.1开始-程序-管理工具-任务计划程序;
2.2新建基本任务;
2.3注意的一点是,在"编辑操作"窗口,在"起始于(可选)"这一栏需要填入bat所在目录,否则bat不会执行;
三、执行逻辑
1.将指定前缀的log在同目录创建一个临时文件(对源文件重命名),如:access_200426.log;
2.使用nginx-s命令,从容重启nginx,重新创建log;
3.读access_200426.log文件,将记是2020-04-26产生的日志,转存至./bac/access_200426.log文件中;
4.删除临时文件access_200426.log;
注:同一天可多次执行,转存的log将增量添加;
四、调用方式
pythonnginx_logs_splter.py--nginxConf=nginx.conf--nginxDir=xxxxx--logPrefixs=access,error
参数:
nginxConf=nginx配置文件
nginxDir=nginx目录
logPrefixs=log文件前缀(多个逗号分隔)
五、nginx_logs_splter.py源码
#!/usr/bin/envpython3
#coding=utf-8
importos
importsys
importargparse
importcodecs
importtime,datetime
importre
'''
拆分nginxaccesslog
日志不会自动按天创建,需要辅助任务把日志按天拆分备份,统一日志时间格式;
作者:草青工作室
'''
_version='200426.1'
_isDebug=True
_isDebug=False
deflogSpliter(nginxDir,prefix):
#今日
today=datetime.datetime.now();
yymmdd_today=today.strftime('%y%m%d')
#昨日
yestoday=datetime.date.today()-datetime.timedelta(days=1)
yymmdd_yestoday=yestoday.strftime('%y%m%d')
#logFileFullName=os.path.join(nginxDir,"logs","%s.log"%prefix)
tmpFileFullName=os.path.join(nginxDir,"logs","%s_%s.log"%(prefix,yymmdd_yestoday))
bacFileFullName=os.path.join(nginxDir,"logs","bac","%s-%s.log"%(prefix,yymmdd_yestoday))
print('%s\ntmpFileFullName=%s\nbacFileFullName=%s\n\n'%(
'-'*60,
tmpFileFullName,
bacFileFullName))
start=datetime.datetime.now()
totalCount=0
withcodecs.open(tmpFileFullName,'r','utf-8')asf:
forlineinf.readlines():
totalCount+=1
print('总记录数\t%s\tfileName=%s'%(totalCount,tmpFileFullName))
#针对accesslog的时间格式
dtAccess=re.compile('\d{1,2}/[a-zA-Z]+/\d{4}:\d{1,2}:\d{1,2}:\d{1,2}')
#针对errorlog的时间格式
dtError=re.compile('\d{4}/\d{1,2}/\d{1,2}\d{1,2}:\d{1,2}:\d{1,2}')
#转换accesslog日期格式("24/Apr/2020:23:26:29+0800"to2020-04-2423:26:29)
dtReplace=re.compile('^".+?"|^\[.+?\]')
#增量写备份文件
outputFile=open(bacFileFullName,'a+',encoding='utf-8')
#写备注
outputFile.writelines("#备份时间\t%s\n"%today.strftime('%Y-%m-%d%H:%M:%S'))
outputFile.writelines("#版本号\t%s\n"%_version)
#转存tmp文件
withopen(tmpFileFullName,'r',encoding='utf-8')asf:
rows=0
#按行统计
whileTrue:
rows+=1
ifrows%10000==0:
print('已分析\t%s/%s\t耗时\t%ss'%(rows
,totalCount
,(datetime.datetime.now()-start).seconds))
#------
if_isDebugandrows>=35000:
print('_isDebug=',_isDebug)
break
#------
line=f.readline()
ifnotline:#等价于ifline=="":
break
ifline.startswith('#'):
print("跳过注释内容=>",line)
continue
#时间格式适配
dt=None
if'access'inprefix:
#获取时间"24/Apr/2020:14:43:38+0800"
arr=dtAccess.findall(line)
iflen(arr)==0:
continue
dt=datetime.datetime.strptime(arr[0],'%d/%b/%Y:%H:%M:%S')
#转换时间格式
line=dtReplace.sub('"%s"'%dt.strftime('%Y-%m-%d%H:%M:%S'),line)
elif'error'inprefix:
#获取时间2020/04/2423:37:46
arr=dtError.findall(line)
iflen(arr)==0:
continue
dt=datetime.datetime.strptime(arr[0],'%Y/%m/%d%H:%M:%S')
ifnotdt:
print('日期转换失败dtisnone')
continue
yymmdd_log=dt.strftime('%y%m%d')
#小于昨天继续
ifyymmdd_logyymmdd_yestoday:
print('退出,大于%s'%yymmdd_yestoday)
break
#print(line)
outputFile.writelines("%s"%line)
#关闭输出文件流
ifoutputFile:
outputFile.close()
#分离后删除tmp文件
ifos.path.exists(bacFileFullName):
os.remove(tmpFileFullName)
print('删除临时文件,%s\t%s'%(tmpFileFullName
,notos.path.exists(tmpFileFullName)))
print('\n\n%s\n拆分完成,耗时%s秒\nlog=%s'%('*'*30
,(datetime.datetime.now()-start).seconds
,bacFileFullName))
pass
'''
>>>f=open('test.txt','w')#若是'wb'就表示写二进制文件
>>>f.write('Hello,world!')
>>>f.close()
python文件对象提供了两个“写”方法:write()和writelines()。
write()方法和read()、readline()方法对应,是将字符串写入到文件中。
writelines()方法和readlines()方法对应,也是针对列表的操作。它接收一个字符串列表作为参数,将他们写入到文件中,换行符不会自动的加入,因此,需要显式的加入换行符。
关于open()的mode参数:
'r':读
'w':写
'a':追加
'r+'==r+w(可读可写,文件若不存在就报错(IOError))
'w+'==w+r(可读可写,文件若不存在就创建)
'a+'==a+r(可追加可写,文件若不存在就创建)
对应的,如果是二进制文件,就都加一个b就好啦:
'rb''wb''ab''rb+''wb+''ab+'
'''
deftest():
#"24/Apr/2020:14:43:38+0800"
dt=time.time()
print(time.strftime('%Y-%m-%d%H:%M:%S[%Z]',time.localtime(dt)))
print(time.strftime('%y-%m-%d%I:%M:%S[%Z]',time.localtime(dt)))
print(time.strftime('%d/%b/%Y%H:%M:%S[%Z]',time.localtime(dt)))
print('-'*30)
str='24/Apr/2020:14:43:38'
dt=datetime.datetime.strptime(str,'%d/%b/%Y:%H:%M:%S')
print("%s[%s]=>%s[%s]"%(str,type(str),dt,type(dt)))
str=dt.strftime('%Y-%m-%d%H:%M:%S')
print("%s[%s]"%(str,type(str)))
pass
'''
python中时间日期格式化符号:
%y两位数的年份表示(00-99)
%Y四位数的年份表示(000-9999)
%m月份(01-12)
%d月内中的一天(0-31)
%H24小时制小时数(0-23)
%I12小时制小时数(01-12)
%M分钟数(00=59)
%S秒(00-59)
%a本地简化星期名称
%A本地完整星期名称
%b本地简化的月份名称
%B本地完整的月份名称
%c本地相应的日期表示和时间表示
%j年内的一天(001-366)
%p本地A.M.或P.M.的等价符
%U一年中的星期数(00-53)星期天为星期的开始
%w星期(0-6),星期天为星期的开始
%W一年中的星期数(00-53)星期一为星期的开始
%x本地相应的日期表示
%X本地相应的时间表示
%Z当前时区的名称
'''
defcreateTempFile(nginxConf,nginxDir,prefixArr):
yestoday=datetime.date.today()-datetime.timedelta(days=1)
yymmdd=yestoday.strftime('%y%m%d')
forprefixinprefixArr:
logFileFullName=os.path.join(nginxDir,"logs","%s.log"%prefix)
tmpFileullName=os.path.join(nginxDir,"logs","%s_%s.log"%(prefix,yymmdd))
ifnotos.path.exists(logFileFullName):
print('log文件不已存在:%s'%tmpFileullName)
continue
ifos.path.exists(tmpFileullName):
print('tmp文件已存在:%s'%tmpFileullName)
continue
#备份log
os.rename(logFileFullName,tmpFileullName)
ifnotos.path.exists(tmpFileullName):
print('log重命名失败:%s'%logFileFullName)
continue
print('%srename%s'%(tmpFileullName,os.path.exists(tmpFileullName)))
#重启nginx
cmd='nginx-p%s-c%s-sreload'%(nginxDir,nginxConf)
print('%s\n执行nginxreload命令\n\t%s\n\n'%('-'*60,cmd))
#os.system()将导致进程阻塞
os.system(cmd)
#等待重启
time.sleep(3)
#判断文件是否存在
print('rolad命令已触发,验证log是否新建')
forprefixinprefixArr:
log=os.path.join(nginxDir,"logs",'%s.log'%prefix)
print('\t%srename%s'%(log,os.path.exists(log)))
print('\n')
defmain(nginxConf,nginxDir,logPrefixs):
ifnotnginxDirornotlogPrefixs:
print("参数为空:--nginxDir={}--logPrefixs={}".format(nginxDir,logPrefixs))
return
ifnotos.path.exists(nginxDir):
print("文件不存在:--nginxDir={}".format(nginxDir))
return
conf=os.path.join(nginxDir,nginxConf)
ifnotos.path.exists(conf):
print("nginxconfig不存在:--nginxConf={}".format(conf))
return
prefixArr=logPrefixs.split(',')
#备份+重新加载nginx
createTempFile(nginxConf,nginxDir,prefixArr)
#分离当天的log
forprefixinprefixArr:
try:
print("备份%s文件"%prefix)
logSpliter(nginxDir,prefix)
exceptExceptionasex:
print("备份%s异常"%prefix,ex)
pass
if__name__=='__main__':
parser=argparse.ArgumentParser(description='manualtothisscript')
parser.add_argument('--nginxConf',type=str,default=None)
parser.add_argument('--nginxDir',type=str,default=None)
parser.add_argument('--logPrefixs',type=str,default=None)
args=parser.parse_args()
#test()
'''
功能:
备份执行时间-1天(昨天)的nginxlog,需要指定log的前缀,多个文件名逗号分隔;
运行逻辑:
1.将指定前缀的log在同目录创建一个临时文件(对源文件重命名),如:access_200426.log;
2.使用nginx-s命令,从容重启nginx,重新创建log;
3.读access_200426.log文件,将记是2020-04-26产生的日志,转存至./bac/access_200426.log文件中;
4.删除临时文件access_200426.log;
注:同一天可多次执行,转存的log将增量添加;
调用方式:
pythonnginx_logs_splter.py--nginxConf=nginx.conf--nginxDir=xxxxx--logPrefixs=access,error
参数:
nginxConf=nginx配置文件
nginxDir=nginx目录
logPrefixs=log文件前缀(多个逗号分隔)
windows部署:
1.在nginx目录,创建一个nginx_logs_backup.bat文件;文件内容如下
pythonnginx_logs_splter.py--nginxConf=nginx.conf--nginxDir=xxxxx--logPrefixs=access,error
2.在定时任务中加一个定时任务,调用这个bat文件;
2.1开始-程序-管理工具-任务计划程序;
2.2新建基本任务;
2.3注意的一点是,在"编辑操作"窗口,在"起始于(可选)"这一栏需要填入bat所在目录,否则bat不会执行;
'''
sys.exit(main(args.nginxConf,args.nginxDir,args.logPrefixs))
到此这篇关于浅析python定时拆分备份nginx日志的方法的文章就介绍到这了,更多相关pythonnginx日志内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!