Source

rsync_backup / rsync_backup.py

# -*- 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
from subprocess import call as cmd
import shutil

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):
    """backup contents of src directory into dst directory"""
    return cmd(RSYNC % dict(src=abspath(src),
                            dst=abspath(dst),
                            link_dst=abspath(link_dst)),
               shell=True)


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=""):
    """do a backup from src to dst, shifting dirs first"""
    dirshift(dst, n, token)
    return rsync(src, join(dst, 0, token), join(dst, 1, token))


if __name__ == "__main__":
    if len(sys.argv) != 5:
        print "rsb N token src dst"
        sys.exit(1)
    n, token, src, dst = sys.argv[1:]
    rc = backup(src, dst, int(n), token)
    sys.exit(rc)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.