需求說(shuō)明
需要支持完全和增量備份
周一執(zhí)行完全備份
其他時(shí)間執(zhí)行增量備份
備份文件需要打包為tar文件并使用gzip格式壓縮
編程思路
整體框架需要?jiǎng)?chuàng)建3個(gè)函數(shù),分別實(shí)現(xiàn)完全備份通殃、增量備份、文件加密3種功能:
1.首先導(dǎo)入time模塊界睁,利用if進(jìn)行判斷,如果當(dāng)?shù)貢r(shí)間是星期一兵拢,執(zhí)行完全備份函數(shù)翻斟,否則執(zhí)行增量備份函數(shù),其中说铃,通配符%a代表時(shí)間星期幾縮寫访惜,上傳參數(shù)分別為要備份的原目錄、目標(biāo)目錄腻扇、md5字典存放目錄
2.調(diào)用完全備份函數(shù):
a)首先獲取新文件名债热,將新文件名放入目標(biāo)目錄下,目的是定義備份文件的絕對(duì)路徑幼苛,以寫壓縮方式打開目標(biāo)目錄下新文件窒篱,將原目錄寫入新文件中,完成完全備份舶沿,其中os.path.join作用是將目錄名和文件的基名拼接成一個(gè)完整的路徑
b)了解os.walk()目錄遍歷器輸出文件結(jié)構(gòu)墙杯,利用for循環(huán)將要備份原目錄中文件遍歷出來(lái)作為字典鍵值對(duì)鍵, md5加密結(jié)果作為字典鍵值對(duì)的值(此時(shí)將原目錄中文件作為上傳參數(shù)調(diào)用文件加密函數(shù))括荡,存入空字典中高镐,字典中每個(gè)文件對(duì)應(yīng)一個(gè)md5值,最后將字典寫入到md5字典存放目錄中
3.調(diào)用文件加密函數(shù):將原目錄文件循環(huán)讀取逐一加密畸冲,返回加密結(jié)果
4.調(diào)用增量備份函數(shù):
a)增量備份函數(shù)代碼與完全備份函數(shù)基本一致
b)區(qū)別在于嫉髓,備份前要先以二進(jìn)制讀方式打開md5字典存放目錄,讀取舊數(shù)據(jù)召夹,判斷舊數(shù)據(jù)中鍵對(duì)應(yīng)的加密值與新加密值是否相同岩喷,如果不相同,則將新增內(nèi)容寫入到目標(biāo)文件中(即只備份新數(shù)據(jù))
5.注意:md5主要用于原文件與新文件判斷
源代碼
#!/usr/bin/env python3
#導(dǎo)入模塊
import time
import os
import tarfile
import hashlib
import pickle
from time import? strftime
#用于判斷兩個(gè)文件是否相同,提取每個(gè)文件中的前4字節(jié)的內(nèi)容然后輸出md5碼進(jìn)行比較
def check_md5(fname):
? ? #計(jì)算文件md5值的函數(shù),接收文件名,返回md5值
? ? m=hashlib.md5()
? ? with open(fname,'rb') as fobj:
? ? ? ? while True:
? ? ? ? ? ? data = fobj.read(4096)
? ? ? ? ? ? if not data:
? ? ? ? ? ? ? ? break
? ? ? ? ? ? m.update(data)
? ? #返回文件的md5值
? ? return m.hexdigest()
#完全備份
def full_backup(src,dst,md5file):
? ? #拼接出備份文件的絕對(duì)路徑,文件名_full_日期 格式
? ? fname=os.path.basename(src)
? ? fname='%s_full_%s.tar.gz'%(fname,strftime('%Y%m%d'))
? ? fname=os.path.join(dst,fname)
? ? #完全備份,就是把整個(gè)目錄壓縮
? ? # 與增量備份不同,完全備份無(wú)需比較新老文件的md5值,管他是啥直接全部打包
? ? tar=tarfile.open(fname,'w:gz')
? ? tar.add(src)
? ? tar.close()
? ? #計(jì)算每個(gè)文件的md5值
? ? md5dict={}
? ? for path,folders,files in os.walk(src):
? ? ? ? for file in files:
? ? ? ? ? ? key = os.path.join(path,file)
? ? ? ? ? ? md5dict[key]=check_md5(key)
? ? #將md5值寫入文件
? ? with open(md5file,'wb')as fobj:
? ? ? ? pickle.dump(md5dict,fobj)
#增量備份
def incr_backup(src,dst,md5file):
? ? # 拼接出備份文件的絕對(duì)路徑
? ? fname = os.path.basename(src)
? ? fname = '%s_incr_%s.tar.gz' % (fname, strftime('%Y%m%d'))
? ? fname = os.path.join(dst, fname)
? ? # 計(jì)算每個(gè)文件的md5值
? ? md5dict = {}
? ? for path, folders, files in os.walk(src):
? ? ? ? for file in files:
? ? ? ? ? ? key = os.path.join(path, file)
? ? ? ? ? ? md5dict[key] = check_md5(key)
? ? #讀前一天文件的md5值,老的md5值
? ? with open(md5file,'rb')as fobj:
? ? ? ? oldmd5=pickle.load(fobj)
? ? #找出新增文件和改動(dòng)文件進(jìn)行備份
? ? tar = tarfile.open(fname,'w:gz')
? ? for key in md5dict:
? ? ? ? #判斷新老文件的md5值是否相等,不相等則把值加入tar包
? ? ? ? if oldmd5.get(key)!=md5dict[key]:
? ? ? ? ? ? tar.add(key)
? ? tar.close()
# 更新md5文件
? ? with open(md5file, 'wb')as fobj:
? ? ? ? pickle.dump(md5dict, fobj)
if __name__=='__main__':
? ? src='/tmp/demo/security'
? ? dst='/tmp/demo/backup'
? ? md5file='/tmp/demo/backup/md5.data'
? ? if strftime("%a")=='Mon':
? ? ? ? full_backup(src,dst,md5file)
? ? else:
? ? ? ? incr_backup(src,dst,md5file)
功能測(cè)試
mkdir -p /tmp/demo/backup
cp -r /etc/security /tmp/demo/
完全備份
]# python3 備份程序.py
]# cd /var/tmp/backup/
]# ls
md5.data? security_full_20191111.tar.gz
增量備份
]# touch /tmp/demo/security/1.txt
]# vim /tmp/demo/security/1.txt
]# python3 backup.py
]# ls /tmp/demo/backup/
md5.data? security_full_20191111.tar.gz? security_incr_20191111.tar.gz