Source

rsync_backup / rsync_backup.py

Full commit
Thomas Waldmann e642031 













Thomas Waldmann 6182bd5 
Thomas Waldmann e642031 

Thomas Waldmann b4d9cdb 
Thomas Waldmann e642031 

Thomas Waldmann 6182bd5 


Thomas Waldmann e642031 






Thomas Waldmann 6182bd5 
Thomas Waldmann e642031 
Thomas Waldmann 6182bd5 



Thomas Waldmann e642031 
























Thomas Waldmann 6182bd5 
Thomas Waldmann e642031 

Thomas Waldmann 6182bd5 
Thomas Waldmann e642031 






Thomas Waldmann 6182bd5 





Thomas Waldmann e642031 
# -*- coding: ascii
"""
rsync-based backup with space-efficient hardlinks,
multiple generations, extra token for daily, weekly,
monthly, ... backups.

author: Thomas Waldmann
license: BSD
"""

import os
from os.path import exists, abspath
import sys
import errno
import subprocess
import shutil

RSYNC = "rsync -avH --numeric-ids --link-dest=%(link_dst)s %(src)s/ %(dst)s/"


cmd = subprocess.check_call


def join(path, n, token):
    if n == 0:
        # there is only ONE "0" directory, no token appended
        token = ""
    return os.path.join(path, "%d%s" % (n, token))


def rsync(src, dst, link_dst, **kw):
    """backup contents of src directory into dst directory"""
    cmd(RSYNC % dict(src=abspath(src),
                     dst=abspath(dst),
                     link_dst=abspath(link_dst)),
        shell=True, **kw)


def dirshift(path, n, token):
    """shift the directories below the base path:
       N-1 -> N (kill it later)
       N-2 -> N-1
       ...
       0 -> 1
       create an empty 0
    """
    for i in range(n, 0, -1):
        try:
            os.rename(join(path, i-1, token),
                      join(path, i, token))
        except OSError as err:
            if err.errno != errno.ENOENT:
                # ignore if directory does not exist,
                # otherwise raise
                raise
    os.mkdir(join(path, 0, token))
    del_dir = join(path, n, token)
    if exists(del_dir):
        shutil.rmtree(del_dir)


def backup(src, dst, n, token="", **kw):
    """do a backup from src to dst, shifting dirs first"""
    dirshift(dst, n, token)
    rsync(src, join(dst, 0, token), join(dst, 1, token), **kw)


if __name__ == "__main__":
    if len(sys.argv) != 5:
        print "rsb N token src dst"
        sys.exit(1)
    n, token, src, dst = sys.argv[1:]
    try:
        backup(src, dst, int(n), token)
    except subprocess.CalledProcessError as err:
        rc = err.returncode
    else:
        rc = 0
    sys.exit(rc)