Random   •   Archives   •   RSS   •   About   •   Contact


tar-back is a backup utility to tar and gzip target filesystems.
It supports a custom retention, filter exclusions, and backup directory.

I use tar-back in combination with cron to perform regular backups of all localhost filesystems into /archive/fs. I then have a central long term storage server that collects the /archive partition from every host.


#!/usr/bin/env python

DESCRIPTION = """A backup utility to tar and gzip
target filesystems. Custom retention, filter exclusions and
backup directory.

from os import path
from sys import exit
from shutil import move
from optparse import OptionParser
import tarfile

def filter_exclusions( tarinfo ):
    """Accept tarinfo, return tarinfo or None"""
    if o.filters:
        for filtr in o.filters:
            if filtr in tarinfo.name:
                return None
    return tarinfo

def exclude_exclusions( filename ):
    """Accept filename, return True or False"""
    """support for python 2.6 or lower"""
    if o.filters:
        for filtr in o.filters:
            if filtr in filename:
                return True
    return False

def file_rotate( target, retention = 3 ):
    """file rotation routine"""
    for i in range( retention-2, 0, -1 ): # count backwards
        old_name = "%s.%s" % ( target, i )
        new_name = "%s.%s" % ( target, i + 1 )
        try: move( old_name, new_name  )
        except IOError: pass
    move( target, target + '.1' )

if __name__ == '__main__':

    p = OptionParser()  # create an option parser object

    p.set_description( DESCRIPTION )

    p.add_option( '-t', '--targets',
      help='list of target filesystems to backup (coma delimited)',
      default=None, dest='targets', metavar='"/home"',

    p.add_option( '-b', '--backup-dir',
      help='path to backup directory',
      dest='backdir', metavar='"PATH"',

    p.add_option( '-f', '--filters',
      help='list of filter patterns to exclude (coma delimited)',
      default=None, dest='filters', metavar='".mp3"',

    p.add_option( '-r', '--retention',
      help='backups to retain [default: 3]',
      default=3, type='int', dest='retention', metavar='amount',

    o, args = p.parse_args()  # parse options and args

    extension = '.tar.gz'

    if not o.targets:
        exit( "missing filesystem target, run --help" )
    if not o.backdir:
        exit( "missing backup directory, run --help" )
    if not path.isdir( o.backdir ):
        exit( "backup-dir %s does not exist" % o.backdir )

    if o.filters:
        o.filters = o.filters.split(',')

    o.targets = o.targets.split(',')

    for target in o.targets:
        slug = target.replace( '/', '-' ).lstrip( '-' ) # change / to -

        if slug == '': slug = 'r' # / slug is empty (root)

        tarpath = path.join( o.backdir, slug + extension )

        if path.isfile( tarpath ):
            file_rotate( tarpath, o.retention )

        tar = tarfile.open( tarpath, 'w:gz' )
            tar.add( target, filter=filter_exclusions )
        except TypeError:
            tar.add( target, exclude=exclude_exclusions )

© Russell Ballestrini.