added rejection method
[outofuni/backup.git] / bin / backup
index f69dfa0..4489388 100755 (executable)
@@ -1,5 +1,10 @@
 #!/bin/bash
 
+function log {
+       conf=`basename $config | sed 's/\.conf$//'`
+       [ "$dolog" = "1" ] && echo "`date` - $@" >> $logdir/${conf}.log
+}
+
 if [ -z "$1" ]; then
        echo usage: $0 configfile
        exit -1
@@ -13,6 +18,7 @@ fi
 config=$1
 
 host=`grep ^host $config | cut -d ' ' -f 2`
+aliases="`grep ^aliases $config | cut -d ' ' -f 2-`"
 user=`grep ^user $config | cut -d ' ' -f 2`
 homedirs="` grep ^homedirs $config | cut -d ' ' -f 2-`"
 extradirs="`grep ^extradirs $config | cut -d ' ' -f 2-`" 
@@ -20,65 +26,176 @@ replicas=`grep ^replicas $config | cut -d ' ' -f 2`
 oldest=`grep ^oldest $config | cut -d ' ' -f 2`
 data=`grep ^data $config | cut -d ' ' -f 2`
 bandwidth=`grep ^bandwidth $config | cut -d ' ' -f 2`
+bwconn="`grep ^bandwidth $config | cut -d ' ' -f 3-`"
+compression=`grep ^compression $config | cut -d ' ' -f 2`
+compconn="`grep ^compression $config | cut -d ' ' -f 3-`"
+cipher=`grep ^cipher $config | cut -d ' ' -f 2`
+ciconn=`grep ^cipher $config | cut -d ' ' -f 3-`
+logdir=`grep ^logdir $config | cut -d ' ' -f 2`
 
-ping -c1 $host > /dev/null 2>&1
-ret=$?
+dolog=0
+if [ ! -z "$logdir" ]; then
+       mkdir -p $logdir
+       [ -d $logdir ] && dolog=1
+fi
 
-if [ "$ret" = "0" ]; then
-       echo "host $host is online ..."
-else
-       echo "host $host unreachable ..."
+hit=0
+for conn in $host $aliases; do
+       ping -c1 $conn > /dev/null 2>&1
+       ret=$?
+       if [ "$ret" = "0" ]; then
+               remote=$conn
+               break
+       fi
+done
+if [ -z "$remote" ]; then
+       log "host $host ($aliases) unreachable ..."
        exit -3
+else
+       log "host $host (via $remote) is online ..."
+fi
+
+if [ ! -z "`ssh $user@$remote 'cat ~/.backup | grep ^no'`" ]; then
+       log "backup rejected by client ..."
+       exit 0
+fi
+
+comp=6
+if [ ! -z "$compression" ]; then
+       comp=$compression
+       for cpair in "$compconn"; do
+               ch=`echo $cpair | cut -d ':' -f 1`
+               if [[ "$remote" == "$ch"* ]]; then
+                       cl=`echo $cpair | cut -d ':' -f 2`
+                       [[ "$cl" == [0-9] ]] && comp=$cl
+               fi
+       done
+fi
+rcomp="-z --compress-level $comp"
+log using compression level $comp ...
+
+bw=0
+if [ ! -z "$bandwidth" ]; then
+       bw=$bandwidth
+       for bwpair in "$bwconn"; do
+               ch=`echo $bwpair | cut -d ':' -f 1`
+               if [[ "$remote" == "$ch"* ]]; then
+                       bwl=`echo $cpair | cut -d ':' -f 2`
+                       [ ! -z "$bwl" ] && bw=$bwl
+               fi
+       done
+fi
+rbw="--bwlimit=$bw"
+log applying bandwidth of $bw ...
+
+ciph=""
+if [ ! -z "$cipher" ]; then
+       ciph=$cipher
+       for cipair in "$ciconn"; do
+               ch=`echo $cipair | cut -d ':' -f 1`
+               if [[ "$remote" == "$ch"* ]]; then
+                       cl=`echo $cipair | cut -d ':' -f 2`
+                       [ ! -z "$cl" ] && ciph=$cl
+               fi
+       done
+fi
+if [ ! -z "$ciph" ]; then
+       log using cipher $ciph ...
 fi
 
 if [ ! -d $data ]; then
-       echo "no data directory ..."
+       log no data directory ...
        exit -4
 fi
+log backing up to $data ...
 
 today=`date -I`
 backupdir=$data/${user}_at_${host}
-
 cbd=$backupdir/$today
-mkdir -p $cbd
-
-rsync="rsync -azR --delete --bwlimit=$bandwidth"
 
 ob=""
+lpb=""
 for pb in $backupdir/[0-9]*; do
+       [ ! -d $pb ] && continue
        bdd=`basename $pb`
        if [ ! -f $backupdir/.$bdd ]; then
                if [ "$pb" != "$cbd" ]; then
                        rm -rf $cbd
                        mv $pb $cbd
+                       log continuing $pb as $cbd ...
                fi
-
-               rsrc=""
-               for dir in $homedirs; do
-                       rsrc="$rsrc :/home/$user/$dir"
-               done
-               rsrc="`echo $rsrc | sed 's/^\ //'`"
-               for dir in $extradirs; do
-                       rsrc="$rsrc :$dir"
-               done
-               $rsync $user@$host$rsrc $cbd
-               ret=$?
-               [ "$ret" != "0" ] && exit -50
-               touch $backupdir/.$pb
+       else
+               lpb=$pb
+               ob="$ob $pb"
        fi
-       ob="$ob $pb"
 done
 
+
+if [ ! -d $cbd ]; then
+       if [ ! -z "$lpb" ]; then
+               cp -r $lpb $cbd
+               log starting backup $today from $lpb ...
+       else
+               mkdir -p $cbd
+               log starting backup $today from scratch ...
+       fi
+fi
+
+if [ ! -f $backupdir/.$today ]; then
+       rsrc=""
+       for dir in $homedirs; do
+               rsrc="$rsrc :/home/$user/$dir"
+       done
+       rsrc="`echo $rsrc | sed 's/^\ //'`"
+       for dir in $extradirs; do
+               rsrc="$rsrc :$dir"
+       done
+       [ ! -z "$homedirs" ] && \
+               log backing up home directories $homedirs ...
+       [ ! -z "$extradirs" ] && \
+               log backing up directories $extradirs ...
+
+       if [ -z "$ciph" ]; then
+               rsync=(rsync -aR $rcomp --delete $rbw $user@$remote$rsrc $cbd)
+       else
+               rsync=(rsync -aR -e "ssh -c $ciph" $rcomp --delete)
+               rsync+=($rbw $user@$remote$rsrc $cbd)
+       fi
+       "${rsync[@]}"
+
+       ret=$?
+       if [ "$ret" != "0" ]; then
+               log backup terminated before completion ...
+               exit -50
+       fi
+       
+       touch $backupdir/.$today
+       log "backup $today completed :)"
+else
+       log backup $bdd found completed ...
+fi
+
+[ -z "$replicas" ] && replicas=3
+[ -z "$oldest" ] && oldest=0
+
 cob=`echo $ob | wc -w`
 if [ $cob -gt $replicas ]; then
        ((numdel=cob-replicas))
        todel="`echo $ob | cut -d ' ' -f 1-${numdel}`"
-       echo "to delete: $todel"
-       #for dirdel in $todel; do
-       #       bdd=`basename $dirdel`
-       #       rm -r $dirdel
-       #       rm $backupdir/$bdd
-       #done
+       for dirdel in $todel; do
+               past=`basename $dirdel`
+               ns=`date --date="$today" +%s`
+               ps=`date --date="$past" +%s`
+               ((delta=(ns-ps)/86400))
+               if [ $delta -gt $oldest ]; then
+                       log "deleting $dirdel ($delta days old) ..."
+                       bdd=`basename $dirdel`
+                       rm -r $dirdel
+                       rm $backupdir/.$bdd
+               else
+                       log "keeping $dirdel ($delta days old) ..."
+               fi
+       done
 fi
 
 exit 0