直接上代码,仅做学习笔记用,核心代码bak_one_dir_by_zip函数 try-except内
#! /usr/bin/python # -*- coding: utf-8 -*
import logging
import os, sys
import zipfile
import time
import traceback
import re
import subprocess #获取命令行输出的结果
#LOG_FORMAT = "%(asctime)s %(name)s %(levelname)s %(pathname)s %(message)s "#配置输出日志格式
LOG_FORMAT = "%(message)s " #简要的格式,只包含输入文本
DATE_FORMAT = '%Y-%m-%d %H:%M:%S %a ' #配置输出时间的格式,注意月份和天数不要搞乱了
LOG_PATH = os.path.join(os.getcwd(),'bak_coll_app.log')
logging.basicConfig(level=logging.DEBUG,
format=LOG_FORMAT,
datefmt = DATE_FORMAT ,
filemode='w', #覆盖之前的记录 'a'是追加
filename=LOG_PATH #有了filename参数就不会直接输出显示到控制台,而是直接写入文件
)
ROOT_PATH='/home/jzcj'
BACK_APPS=['tomcat', 'titan', 'antab', 'agent', 'src']
#压缩单个目录,注意入参需要时绝对路径,是否按绝对路径压缩,建议选按相对路径压缩,即isAbs = False
def bak_one_dir_by_zip(folder, isAbs):
folder = os.path.abspath(folder) #make sure folder is abslote
#get current time by yyyymmdd format
date_ymd=time.strftime('%Y%m%d',time.localtime(time.time()))
number = 1
while True:
zipFilename = os.path.basename(folder) + '_' + date_ymd + '_' + str(number) +'.zip'
#basename是最后一个斜杠后的字符串,dirname是最后一个斜杠钱的字符串
if not os.path.exists(zipFilename):
break
number += 1
#create zipfile
print('Try create %s and adding files...' %(zipFilename))
logging.debug('Try create %s and adding files...' %(zipFilename))
# can user with-as too ??
backupzip = zipfile.ZipFile(zipFilename, 'w',zipfile.ZIP_STORED,allowZip64=True)
'''
zf = zipfile.ZipFile(zipfilename, "w", zipfile.ZIP_STORED,allowZip64=True)
四个参数:zip文件包含路径的名字,"w"/"r"表示写或者读,zipfile.ZIP_STORED表示存储格式(还可以是zipfile.zlib.DEFLATED表示压缩格式),
allowZip64=True这个参数是在处理大文件时使用的,默认为False。如果没有设置为True而处理大文件时会提示 zip file size require ZIP64 extensions.
'''
#正则表达式排除日志记录文件
exfile1 = re.compile(r'(.*)?(\.log)$')
exfile2 = re.compile(r'^(log\.)(.*)?')
exfile3 = re.compile(r'(.*)\.log\.(.*)')
exfile4 = re.compile(r'snapshot(.*)')
try:
#list all dir and zip to zipfile
#walk the entire folder tree and compress the files in each folder
for foldeName, subfolders, fileNames in os.walk(folder):
#Add the current folder to the ZIP file
if True == isAbs:
backupzip.write(foldeName)
else:
#相对路径压缩,而不是绝对路径
fpath = foldeName.replace(folder, '')
#下面这句很必要,需要理解,如果当前目录替换了根目录就是空值‘’,那么说明当前目录为一级或最外围目录,
#如果不是'',说明当前目录是下一层子目录,则对子目录添加系统的分隔符
#如果不加这一句,将会把所有文件压缩到根目录下
fpath = fpath and fpath + os.sep or ''
#python里面,0、’’、[]、()、{}、None为假,其它任何东西都为真
# (对于or,如果没有真值,返回的是最后一个假值,如果有真值,则返回的是第一个真值。)
# (对于and,如果没有假值,返回的是最后一个真值,如果有假值,则返回的是第一个假值。)
#Add all the files in this folder to the ZIP file
for filename in fileNames:
#正则表达排除log日志文件
if (None != exfile1.search(filename) or \
None != exfile2.search(filename) or \
None != exfile3.search(filename) or \
None != exfile4.search(filename)
):
logging.debug('In forlder %s current file is %s , and no need to compress,continue...' \
%(foldeName, filename))
continue #跳过以下所有步骤,进行下一个文件压缩
else:
logging.debug('Adding zipfiles from file %s/%s...' %(foldeName, filename))
newBase = os.path.basename(folder) + '_'
if filename.startswith(newBase) and filename.endswith('.zip'):
continue #不备份之前的备份压缩文件
if True == isAbs:
#以绝对路径压缩
backupzip.write(os.path.join(foldeName, filename))
#backupzip.write(os.sep.join([foldeName, filename]))
else:
#相对路径压缩而不是绝对路径
backupzip.write(os.path.join(foldeName, filename),fpath+filename)
#backupzip.write(os.sep.join([foldeName, filename]),fpath+filename) #os.sep 操作系统文件夹分割符 /或\\
except:
logging.debug('in zipfile %s , some error happend,trace-info like: %s ' %(zipFilename, traceback.format_exc()))
logging.debug('some bad things happend, close backupzip and return.')
print('some bad things happend, close backupzip and return.')
backupzip.close()
return None
#zipfile write success normal finished
backupzip.close()
print('zip %s Done!' %(zipFilename))
logging.debug('zip %s Done!' %(zipFilename))
return None
#调用bak_one_dir_by_zip 逐个文件夹压缩
def bak_all_dir():
abs_bak_path = []
for app_name in BACK_APPS:
abs_bak_path.append(os.path.join(ROOT_PATH, app_name))
#删除旧的备份文件
for app in abs_bak_path:
if os.path.exists(app):
bak_one_dir_by_zip(app,False)
else:
print('No such path or file:%s.' %(app))
def call_shell_rm_old():
zipfile = []
for app_name in BACK_APPS:
shell_cmd = 'rm -rf ' + app_name + '*.zip'
print('excute shell_cmd = %s' %(shell_cmd))
try:
subpip = subprocess.Popen(shell_cmd, shell=True,stdout=subprocess.PIPE) #将命令行输出的结果写入PIPE
#re = os.system(doredis)
except:
logging.debug('some error happedn in delete %s*.zip ,trace-info like: %s ' \
%(app_name, traceback.format_exc()))
return None
if __name__=='__main__':
#调用系统命令行删除旧的备份文件
call_shell_rm_old()
bak_all_dir()