Skip to content

Instantly share code, notes, and snippets.

Revisions

  1. @morhekil morhekil revised this gist Jan 12, 2014. 1 changed file with 7 additions and 0 deletions.
    7 changes: 7 additions & 0 deletions rsync-incremental-backup.sh
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,12 @@
    #!/bin/bash

    # Rsync based file backup script, with hard-linking enabled.
    #
    # Runtime options:
    # -n - dry-run; do nothing, just display what is going to happen on a real run
    # -v - verbose output; print out what is being backed up
    #

    # set to your rsync location
    RSYNC_BIN="/usr/bin/rsync"
    # location of the files to back up (WITH a trailing slash)
  2. @morhekil morhekil created this gist Jan 12, 2014.
    67 changes: 67 additions & 0 deletions rsync-incremental-backup.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,67 @@
    #!/bin/bash

    # set to your rsync location
    RSYNC_BIN="/usr/bin/rsync"
    # location of the files to back up (WITH a trailing slash)
    SOURCE_DIR="/path/to/source_dir/"
    # target dir for backups (NO trailing slash)
    BACKUP_DIR="/path/to/backup_dir"
    # how many backups to keep
    KEEP_BACKUPS=7

    #
    # END OF CONFIGURATION
    #

    # takes command to execute as the first argument, and then
    # 1. Prints it if we're in verbose mode
    # 2. If we're in dry-run mode, as the second argument is nil - does nothing
    # 3. If we're not in dry-run mode - executes the command
    # 4. If we're in dry-run mode, but the 2nd argument is not nill - executes the commad
    # (i.e. when it's constructed to dry-run by itself)
    function docmd {
    if [ "$verbose" -eq 1 ]; then echo "--- $1"; fi
    # if [ [ "$dry_run" -eq 0 ] -o [ -n $2 ] ]; then `$1`; fi
    if [ "$dry_run" -eq 0 ] || [ -n "$2" ]; then $1; fi
    }

    # reset getopts
    OPTIND=1
    # set default values for configuration params
    dry_run=0
    verbose=0

    while getopts "vn" opt; do
    case "$opt" in
    v) verbose=1;
    ;;
    n) dry_run=1; verbose=1;
    ;;
    esac
    done

    # generate directory name that we'll be syncing into
    timestamp=`date +"%Y.%m.%d.%H.%M.%S"`
    sync_target="$BACKUP_DIR/$timestamp"

    # extra rsync options
    rsync_options=""
    # get a directory to link against, if any
    link_target=`ls -1 $BACKUP_DIR | tail -n1`
    # if we have a valid link directory - set it as an option for rsync
    if [ -n "$link_target" ]; then rsync_options="--link-dest=$BACKUP_DIR/$link_target"; fi
    # if we're in verbose mode - set it for rsync
    if [ "$verbose" -eq 1 ]; then rsync_options="$rsync_options -v"; fi
    # if we're in dry run mode - set it for rsync
    if [ "$dry_run" -eq 1 ]; then rsync_options="$rsync_options -n"; fi

    docmd "mkdir -p $sync_target"
    docmd "$RSYNC_BIN -a --delete $rsync_options $SOURCE_DIR $sync_target" 1

    backups_count=`ls -1 $BACKUP_DIR | wc -l`
    backups_to_remove=$(($backups_count-$KEEP_BACKUPS))
    if [ $backups_to_remove -gt 0 ]; then
    for d in `ls -1 $BACKUP_DIR | head -n$backups_to_remove`; do
    docmd "rm -rf $BACKUP_DIR/$d"
    done
    fi