Previously there was write using MD5 method to do differential backup, but this MD5 way to write the following problems:
md5sum Get a problem with MD5 value for some soft connections
• Backup to an empty directory is not supported because md5sum cannot get the MD5 value of an empty directory
• Modification of permissions md5sum cannot be judged
Solution:
Take advantage of File Mtime CTime
Mtime (Modified time) is changed when writing to a file with changes to the contents of the file.
CTime (Create time) is changed as the content of the inode changes while writing to a file, changing owner, permission, or link settings.
Nonsense not much to say directly on the code:
#!/usr/bin/env Pythonimport time,os,sys,cpicklefileinfo = {}def Logger (time,filename,status,filenum): F = open (' Backup.log ', ' a ') f.write ("%s\t%s\t%s\t\t%s\n"% (time,filename,status,filenum)) def tar (sdir,ddir,filenum): Command = "Tar zcf%s%s >/dev/null 2>&1"% (Ddir + ". tar.gz", SDir) if Os.system (command) = = 0:logger (Time.strftime (' %F%x '), Ddir + ". tar.gz", ' success ', FileNum) Else:logger (Time.strftime ('%F%x '), Ddir + ". tar.gz", ' failed ', FileNum) def Fullbak (path): FileNum = 0 for root,dirs,files in Os.walk (path): for name in Files:file = Os.path.join (Root, NA Me) Mtime = os.path.getmtime (file) CTime = os.path.getctime (file) fileinfo[file] = (mtime,ctime) filen Um + = 1 f = open (P, ' W ') Cpickle.dump (fileinfo,f) f.close () tar (s,d,filenum) def diffbak (path): For Root,dirs,files in Os.walk (PATH): for name in Files:file = Os.path.join (root,name) mtime = os.path.getmtime (file) CTime = Os.path.getctime (file) fileInfo[File] = (mtime,ctime) if Os.path.isfile (p) = = 0:f = Open (P, ' W ') f.close () if Os.stat (p). st_size = = 0:f = Ope N (P, ' W ') Cpickle.dump (fileinfo,f) FileNum = Len (Fileinfo.keys ()) f.close () Print FileNum tar (s,d,filenum) else:f = open (P) Old_fileinfo = Cpickle.load (f) f.close () difference = Dict (set (Fileinfo.items ()) ^set (Old_fil Einfo.items ())) FileNum = Len (difference) print filenum difference_file = '. Join (Difference.keys ()) Print di Fference_file tar (difference_file,d,filenum) f = open (P, ' W ') Cpickle.dump (fileinfo,f) f.close () def Usage (): P Rint "Syntax:python file_bakcup.py pickle_file model Source_dir FILENAME_BK model:1:full backup 2:differentia L Backup Example:python file_backup.py fileinfo.pk 2/etc etc_$ (date +%f) explain:automatically add '. tar.gz ' su Ffix "Sys.exit () If Len (sys.argv)! = 5:usage () P = sys.argv[1]m = Int (sys.argv[2]) S = Sys.argv[3]d = Sys.argv[4]if M = = 1:fullbak (S) elif M= = 2:diffbak (S) else:print "\033[;31mdoes not support this mode\033[0m" Usage ()
Test:
$ python file_backup.py data.pk 1 data data_$ (date +%f) #全备份 $ > Data/www.jb51.net #测试创建文件, modify file permissions $ chmod 777 Data/py/esh op_bk/data.db$ python file_backup.py data.pk 2 data data_$ (date +%f) _1 #备份改变的文件2data/py/eshop_bk/data.db data/ Www.jb51.net
Look at the blogger's code, very inspired, but there is a problem, if I finished the full backup, delete one of the files, then make a differential backup, can detect the deleted files, but the execution of tar will be wrong, because this file is no longer exist, so before the tar is executed, It is best to use os.path.exists () to determine if the differential file path exists, if it does not, do not execute tar, feedback a file delete information.