Skip to content
Snippets Groups Projects
rdiff.in 7.97 KiB
Newer Older
  • Learn to ignore specific revisions
  • # -*- mode: sh; sh-basic-offset: 3; indent-tabs-mode: nil; -*-
    
    # vim: set filetype=sh sw=3 sts=3 expandtab autoindent:
    
    elijah's avatar
    elijah committed
    #
    # rdiff-backup handler script for backupninja
    # requires rdiff-backup
    #
    
    
    elijah's avatar
    elijah committed
    ### FUNCTIONS ###
    
    function test_connection() {
    
       # given a user and host,
       # tests the connection.
       # if user or host is missing, returns 0
       # (ie, assume it's a local connection).
       if [ $# -lt 2 ]; then
          debug "(local is assumed to be a good connection)"
          return 0
       fi
       local user=$1
       local host=$2
       debug "ssh $sshoptions -o PasswordAuthentication=no $host -l $user 'echo -n 1'"
       local ret=`ssh $sshoptions -o PasswordAuthentication=no $host -l $user 'echo -n host is alive'`
       if echo $ret | grep "host is alive"; then
          debug "Connected to $host as $user successfully"
       else
          fatal "Can't connect to $host as $user."
       fi
    
    elijah's avatar
    elijah committed
    }
    
    function get_version() {
    
       # given no arguments, returns the local version.
       # given a user and host, returns the remote version.
       # if user or host is missing, returns the local version.
    
       if [ "$#" -lt 2 ]; then
          debug "$RDIFFBACKUP -V"
          echo `$RDIFFBACKUP -V`
       else
          local user=$1
          local host=$2
          debug "ssh $sshoptions $host -l $user '$RDIFFBACKUP -V'"
    
          version=`ssh $sshoptions $host -l $user "$RDIFFBACKUP -V"`
          if [ $? = 127 ]; then
             fatal "Unable to execute rdiff-backup on remote server. It probably isn't installed"
          else
             echo "$version" | grep rdiff-backup
          fi
    
    elijah's avatar
    elijah committed
    }
    
    function check_consistency() {
    
       local section=$1
       local type=$2
       local user=$3
       local host=$4
       if [ "$type" == "local" ]; then
          if [ "$user" != "" ]; then
             warning "User should not be specified for local $section."
          fi
          if [ "$host" != "" ]; then
             warning "Host should not be specified for local $section."
          fi
       fi
       if [ "$type" == "remote" ]; then
          if [ "$user" == "" ]; then
             fatal "User must be specified for remote $section."
          fi
    
          if [ "$host" == "" ]; then
    
             fatal "Host must be specifed for remote $section."
          fi
       fi
    
    function check_cstream() {
    
       local cstream=$1
       if [ ! -x $cstream ]; then
          fatal "Can't find your cstream binary (trying: $cstream). If you use bwlimit you must have cstream installed."
       fi
    
    elijah's avatar
    elijah committed
    ### GET CONFIG ###
    
    
    getconf options
    
    getconf testconnect yes
    getconf nicelevel 0
    
    getconf bwlimit
    
    getconf ignore_version no
    
    getconf output_as_info no
    
    elijah's avatar
    elijah committed
    setsection source
    getconf type; sourcetype=$type
    
    elijah's avatar
    elijah committed
    getconf user; sourceuser=$user
    getconf host; sourcehost=$host
    check_consistency "source" "$type" "$user" "$host"
    
    elijah's avatar
    elijah committed
    getconf label
    
    getconf keep 60
    
    elijah's avatar
    elijah committed
    getconf include
    
    micah's avatar
    micah committed
    getconf vsinclude
    
    elijah's avatar
    elijah committed
    getconf exclude
    
    setsection dest
    getconf directory; destdir=$directory
    # strip trailing /
    destdir=${destdir%/}
    getconf type; desttype=$type
    getconf user; destuser=$user
    getconf host; desthost=$host
    
    micah's avatar
    micah committed
    getconf sshoptions
    
    elijah's avatar
    elijah committed
    check_consistency "destination" "$type" "$user" "$host"
    
    
    if [ -n "$sshoptions" ] && echo $options | grep -qv "remote-schema"; then
    
       options="$options --remote-schema 'ssh -C $sshoptions %s rdiff-backup --server'"
    
    elijah's avatar
    elijah committed
    ### CHECK CONFIG ###
    
    elijah's avatar
    elijah committed
    
    
    # If vservers are configured, check that the ones listed in $vsnames do exist.
    
    if [ $vservers_are_available = yes ]; then
       if [ "$vsnames" = all ]; then
          vsnames="$found_vservers"
       else
          if ! vservers_exist "$vsnames" ; then
    
             fatal "At least one of the vservers listed in vsnames ($vsnames) does not exist."
    
          fi
       fi
       if [ -n "$vsinclude" ]; then
          info "Using vservers '$vsnames'"
          usevserver=yes
       fi
    else
       [ -z "$vsinclude" ] || warning 'vservers support disabled in backupninja.conf, vsincludes configuration lines will be ignored'
    
    elijah's avatar
    elijah committed
    # check the connection at the source and destination
    
    if [ "$testconnect" = "yes" ] || [ "${test}" -eq 1 ]; then
    
       test_connection $sourceuser $sourcehost
       test_connection $destuser $desthost
    
    elijah's avatar
    elijah committed
    fi
    
    
    if [ "$ignore_version" != "yes" ]; then
    
       # see that rdiff-backup has the same version at the source and destination
       sourceversion=`get_version $sourceuser $sourcehost`
       destversion=`get_version $destuser $desthost`
       if [ "$sourceversion" != "$destversion" ]; then
          fatal "rdiff-backup does not have the same version at the source and at the destination."
       fi
    
    elijah's avatar
    elijah committed
    
    
    elijah's avatar
    elijah committed
    # source specific checks
    
    case $sourcetype in
       remote ) execstr_sourcepart="$sourceuser@$sourcehost::/" ;;
       local  ) execstr_sourcepart="/" ;;
       *      ) fatal "sourcetype '$sourcetype' is neither local nor remote" ;;
    
    elijah's avatar
    elijah committed
    esac
    
    elijah's avatar
    elijah committed
    
    
    elijah's avatar
    elijah committed
    # destination specific checks
    [ "$destdir" != "" ] || fatal "Destination directory not set"
    
    case $desttype in
       remote ) execstr_destpart="$destuser@$desthost::$destdir/$label" ;;
       local  ) execstr_destpart="$destdir/$label" ;;
       *      ) fatal "desttype '$desttype' is neither local nor remote" ;;
    
    elijah's avatar
    elijah committed
    esac
    
    elijah's avatar
    elijah committed
    ### REMOVE OLD BACKUPS ###
    
    elijah's avatar
    elijah committed
    
    
    if [ "$keep" != yes ]; then
    
       if [ "`echo $keep | tr -d 0-9`" == "" ]; then
    
       # add D if no other date unit is specified
    
          keep="${keep}D"
       fi
    
       removestr="$RDIFFBACKUP $options --force --remove-older-than $keep "
       if [ "$desttype" == "remote" ]; then
          removestr="${removestr}${destuser}@${desthost}::"
       fi
       removestr="${removestr}${destdir}/${label}";
    
       debug "$removestr"
       if [ $test = 0 ]; then
          output="`su -c "$removestr" 2>&1`"
          if [ $? = 0 ]; then
    
             if [ "$output_as_info" == "yes" ]; then
                info $output
             else
                debug $output
             fi
    
             info "Removing backups older than $keep days succeeded."
    
             warning $output
             warning "Failed removing backups older than $keep."
    
    elijah's avatar
    elijah committed
    fi
    
    
    # Add cstream
    
    
    if [ ! -z $bwlimit ]; then
    
       check_cstream $CSTREAM;
       if [ "$desttype" = "remote" ]; then
          RDIFFBACKUP="$RDIFFBACKUP --remote-schema 'cstream -t $bwlimit | ssh %s \''rdiff-backup --server\'''"
       elif [ "$sourcetype" = "remote" ]; then
          RDIFFBACKUP="$RDIFFBACKUP --remote-schema 'ssh %s \''rdiff-backup --server\'' | cstream -t $bwlimit'"
       else
          fatal "You specified a bandwidth limit but neither your source nor destination types are remote."
       fi
    
    elijah's avatar
    elijah committed
    ### EXECUTE ###
    
    execstr="$RDIFFBACKUP $options --print-statistics "
    
    elijah's avatar
    elijah committed
    
    
    symlinks_warning="Maybe you have mixed symlinks and '*' in this statement, which is not supported."
    
    
    elijah's avatar
    elijah committed
    # TODO: order the includes and excludes
    # excludes
    
    SAVEIFS=$IFS
    IFS=$(echo -en "\n\b")
    
       case "$str" in
          @*) execstr="${execstr}--exclude-globbing-filelist '${str#@}' " ;;
          *) execstr="${execstr}--exclude '$str' " ;;
       esac
    
    elijah's avatar
    elijah committed
    done
    
    SAVEIFS=$IFS
    IFS=$(echo -en "\n\b")
    
       [ "$i" != "/" ] || fatal "Sorry, you cannot use 'include = /'"
       str="${i//__star__/*}"
    
       case "$str" in
       @*) execstr="${execstr}--include-globbing-filelist '${str#@}' " ;;
       *) execstr="${execstr}--include '$str' " ;;
       esac
    
    elijah's avatar
    elijah committed
    done
    
    elijah's avatar
    elijah committed
    
    
    micah's avatar
    micah committed
    # vsinclude
    
    if [ $usevserver = yes ]; then
    
          SAVEIFS=$IFS
          IFS=$(echo -en "\n\b")
    
             str="${vi//__star__/*}"
             str="$VROOTDIR/$vserver$str"
    
                execstr="${execstr}--include '$str' "
    
                warning "vsinclude statement '${vi//__star__/*}' will be ignored for VServer $vserver. $symlinks_warning"
    
    elijah's avatar
    elijah committed
    # exclude everything else
    
    [ "$include" != "" -o "$vsinclude" != "" ] && execstr="${execstr}--exclude '/*' "
    
    elijah's avatar
    elijah committed
    # include client-part and server-part
    
    elijah's avatar
    elijah committed
    execstr="${execstr}$execstr_sourcepart $execstr_destpart"
    
    elijah's avatar
    elijah committed
    
    
    if [ $test = 0 ]; then
    
       output=`nice -n $nicelevel su -c "$execstr" 2>&1`
       if [ $? = 0 ]; then
    
          if [ "$output_as_info" == "yes" ]; then
             info $output
          else
             debug $output
          fi
    
          info "Successfully finished backing up source $label"
       else
    
          error $output
          fatal "Failed backup up source $label"
    
    elijah's avatar
    elijah committed
    
    return 0