Skip to content

Instantly share code, notes, and snippets.

@creshal

creshal/backup-rsync

Created Oct 15, 2015
Embed
What would you like to do?
#! /bin/python
import sys,os,time,glob,shutil
import subprocess as sp
def backup (src,dst):
src = sys.argv[1]
exclude_file = os.path.join (src,'.backup-exclude')
dst = sys.argv[2]
dst_dir = os.path.join (dst,'%i'%time.time())
lnk_dir = get_old_backups (dst)[-1]
try:
rsync_call = ['rsync','-aHAxXP','--exclude=lost+found',src,dst_dir]
if lnk_dir:
rsync_call.append ('--link-dest='+lnk_dir)
if ':' in dst:
rsync_call.append ('-M--fake-super')
if os.path.exists (exclude_file):
rsync_call.append ('--exclude-from='+exclude_file)
print (' '.join (rsync_call))
sp.check_call (rsync_call)
except sp.CalledProcessError as e:
print (e)
sys.exit (1)
prune_backups (dst)
def get_old_backups (dst):
if os.path.isdir (dst):
old_backups = list(map (os.path.abspath, glob.glob (dst+'/*')))
else:
host,directory = dst.split(':',1)
directory = directory if directory.startswith('/') else '$PWD/'+directory
find_call = ['ssh',host,'find',directory,'-mindepth','1','-maxdepth','1',
'-type','d']
old_backups = sp.check_output(find_call).decode('utf8').strip().split('\n')
if not len (old_backups): return
return sorted(old_backups)
def prune_backups (dst):
old_backups = get_old_backups (dst)
remote = not os.path.isdir(dst)
if remote:
host,directory = dst.split(':',1)
while len (old_backups) > 3:
print ('Pruning old backup '+old_backups[0])
if remote:
try:
sp.call (['ssh',host,'rm','-r',old_backups.pop (0)])
except sp.CalledProcessError as e:
print ('Failed to delete old backup:\n'+e)
else:
shutil.rmtree (old_backups.pop(0))
if __name__ == '__main__':
if len(sys.argv) != 3 or '-h' in sys.argv:
print ('Usage: %s rsyncsource rsynctarget'%sys.argv[0])
sys.exit ()
backup (sys.argv[1],sys.argv[2])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment