Welcome, guest | Sign In | My Account | Store | Cart

Windows backup utility, with remote copy, and auto cleanup. Uses zip libs. Used in a production network environment and works very well dumping both target files and remote target files over the network so you are not limited to saving a copy local.

Python, 179 lines
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
'''
BACK UP AND ARCHIVING TOOL by MoHaWke #B0)
http://www.digitaldarknet.net/
Date: December 2004
Install python 2.3 from http://www.python.org
Setup source and target paths, retention dates.
Setup to run in Windows Task Scheduler.
'''
import zlib, zipfile, os, time, sys
import win32api, win32file
#=================================================

#/////////////////////////////////////////////////
# FUNCTION; saves copy of original source zips
#/////////////////////////////////////////////////
def remote_Save(target, remote_target):
    bFailIfExists = 0
    for backups in os.listdir(target):
        if backups[-3:].lower() == 'zip':
            win32file.CopyFile(target+'\\'+backups, remote_target+'\\'+backups, bFailIfExists)
            
#/////////////////////////////////////////////////
# FUNCTION; Deletes remote and local zips based
#on user defined retention. 
#/////////////////////////////////////////////////   
def clean_dir(target, remote_target, target_count, remote_count):
    # Clean main backup directory.
    dict_trg = {}; flist=[]
    target_dir = os.listdir(target)
    for x in target_dir:
        timestamp=int(x.split('_')[0])
        filename=x.split('_')[-1]
        if not dict_trg.has_key(filename):
            dict_trg[filename]=[]
        dict_trg[filename].append(timestamp)
        
    for arch, flist in dict_trg.items():
        if len(flist)>target_count:
            flist.sort()
            sort_list=str(flist[0])
            os.remove(target+'/'+sort_list+'_'+arch)
       
    # Clean up remote location.
    dict_rmt = {}; flist=[]
    if remote_target:
        remote_dir = os.listdir(remote_target)
        for x in remote_dir:
            timestamp=x.split('_')[0]
            filename=x.split('_')[-1]
            if not dict_rmt.has_key(filename):
                dict_rmt[filename]=[]
            dict_rmt[filename].append(timestamp)
            
    for arch, flist in dict_rmt.items():
        if len(flist)>remote_count:
            flist.sort()
            sort_list=str(flist[0])
            os.remove(remote_target+'/'+sort_list+'_'+arch)

#/////////////////////////////////////////////////
# FUNCTION; Recusive directory zipping.
#/////////////////////////////////////////////////
def archive_dir(source, arcname, target, arc_time):
    # Set the filename and destination.
    arcname  = str(arc_time)+'_'+arcname+'.zip'  # Archive filename
    target   = str(target+'/'+arcname)           # Path to storage...
    
    dirs = [str(source)] # Set initial "root" directories to pop.
    zipObj = zipfile.ZipFile(target,'w',zipfile.ZIP_DEFLATED)
    
    try:
        while dirs:
            # Loop through and get all sub dirs and files.
            dir_list=dirs.pop(0) # pop next dir.
            try:
                for items in os.listdir(dir_list+'/'):
                    if os.path.isdir(dir_list+'/'+items):
                        # Collect sub dirs for pop.
                        dirs+=[dir_list+'/'+items]
                    elif os.path.isfile(dir_list+'/'+items):
                        # Ignor the archive file if in the dir structure.
                        if items.lower() == arcname: continue
                        if items.lower()[:3] == 'ini': continue #task directory filter.
                        # Write to the zip.
                        zipObj.write(str(dir_list+'/'+items),None,None)
            except:
                pass # Ignor non-accessable directories!

        zipObj.close()
        return 1 # Success...
    
    except Exception, error:
        return error # Backup failed...
    
#//////////////////////////////////////////////////////>
# CONFIGURATION AND PATH SETUPS
#//////////////////////////////////////////////////////>

# SPECIFY SOURCE PATHS; add as many as you like.
# Don't forget to add these to the SOURCE_PATH list below.
path_a   = 'c:/somedir'             # Back up this directory
path_b   = 'c:/someotherdir'        # Back up that directory
path_c   = ''                       # empty...
path_d   = ''                       # empty...
all_drv  = 'c:/'                    # I wouldn't do this! 

# SPECIFY TARGET PATHS.
target = 'c:/backup'                   # save to path local.
remote_target = r'\\server\c$\backup'  # save to path remote; can be a mapped share or local store also.

# CLEAN UP SETTINGS: Removes oldest archive.
target_count = 7  # Days to keep
remote_count = 30 # Days to keep
clean_bu = 1      # 0 turns off cleaning.

# LOG FILE PATH
logpath=os.getcwd()
logfile = logpath+'\\archive_log.log'

# TURN ON OR OFF ? ****
all_drv  = 'off'                                       
#path_a = 'off'
#path_b = 'off'
#path_c = 'off'
#path_d = 'off'
remote = 1   # 0 - turn off remote copy/ 1 = on.

# SOURCE_PATH :: ADD NEW PATHS HERE...
source_paths = [path_a, path_b, path_c, path_d, all_drv]

#//////////////////////////////////////////////////////>
#YOU SHOULDN'T NEED TO CHANGE ANYTHING BELOW THIS LINE
#//////////////////////////////////////////////////////>

tm_stamp = time.ctime()
arc_time = int(time.time())
myname  = win32api.GetComputerName()

# Start Backups...
#========================================>
#========================================> 
# make sure the directories exist.
if not os.path.exists(target): os.mkdir(target)
if remote_target:
    if not os.path.exists(remote_target):
        os.mkdir(remote_target)  

# Run backup.
for source in source_paths:
    if os.path.exists(source):
        arcname = source.split('/')[-1] #strip the sub path for archive filename. 
        try:
            status = archive_dir(source, arcname, target, arc_time)

            # Report and log errors.
            if status != 1:
                open(logfile,'a').write('\n'+tm_stamp+':: '+myname+':: path='+source+'\n Archive unsuccessful - status returned 0') # log
                sys.exit(0) #Back up failed, no since in running the rest.
            open(logfile,'a').write('\n'+tm_stamp+': '+myname+':: '+source+' Successfully backed up.') # log
        except Exception, error:
            open(logfile,'a').write('\n'+tm_stamp+': '+myname+':: path='+source+'\n'+' Error:: '+str(error)) # log
            
#========================================>
# Save remote.
#========================================>
if not remote == 0:
    try:
        remote_Save(target, remote_target)
    except Exception, error:
        open(logfile,'a').write('\n'+tm_stamp+': Remote backup failed:: '+str(error))
        
#========================================>
# Clean up.
#========================================> 
if not clean_bu == 0:
    try:
        clean_dir(target, remote_target, target_count, remote_count)
    except Exception, error:
        open(logfile,'a').write('\n'+tm_stamp+': Clean up failed:: '+str(error))

1 comment

Denis Barmenkov 18 years, 8 months ago  # | flag

Errors.. As I see, remote_Save() was written badly and failed at files, which name ends with 'zip': '123zip', 'zipzipzip', 'zip', that are not *.zip.

backups[-3:].lower() == 'zip'

will be

os.path.splitext(backups)[1].lower() == 'zip'

After this error I placed entire recipe in my own blacklist.