Source

rsync_backup / rsync_backup.py

Thomas Waldmann e642031 













Thomas Waldmann 6182bd5 
Thomas Waldmann e642031 
Thomas Waldmann 65bcd55 
Thomas Waldmann e642031 
Thomas Waldmann b4d9cdb 
Thomas Waldmann e642031 








Thomas Waldmann 6182bd5 
Thomas Waldmann e642031 
Thomas Waldmann 6182bd5 


Thomas Waldmann 65bcd55 
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
from exec_cmd import exec_shell as cmd

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


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)),
        **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)