#!/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 fi if [ ! -f $1 ]; then echo configfile $1 is not a file exit -2 fi config=$1 host=`grep ^host $config | cut -s -d ' ' -f 2` aliases="`grep ^aliases $config | cut -s -d ' ' -f 2-`" user=`grep ^user $config | cut -s -d ' ' -f 2` homedirs="` grep ^homedirs $config | cut -s -d ' ' -f 2-`" extradirs="`grep ^extradirs $config | cut -s -d ' ' -f 2-`" replicas=`grep ^replicas $config | cut -s -d ' ' -f 2` oldest=`grep ^oldest $config | cut -s -d ' ' -f 2` data=`grep ^data $config | cut -s -d ' ' -f 2` bandwidth=`grep ^bandwidth $config | cut -s -d ' ' -f 2` bwconn="`grep ^bandwidth $config | cut -s -d ' ' -f 3-`" compression=`grep ^compression $config | cut -s -d ' ' -f 2` compconn="`grep ^compression $config | cut -s -d ' ' -f 3-`" cipher=`grep ^cipher $config | cut -s -d ' ' -f 2` ciconn=`grep ^cipher $config | cut -s -d ' ' -f 3-` logdir=`grep ^logdir $config | cut -s -d ' ' -f 2` dolog=0 if [ ! -z "$logdir" ]; then mkdir -p $logdir [ -d $logdir ] && dolog=1 fi 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 ^off'`" ]; 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 -s -d ':' -f 1` if [[ "$remote" == "$ch"* ]]; then cl=`echo $cpair | cut -s -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 -s -d ':' -f 1` if [[ "$remote" == "$ch"* ]]; then bwl=`echo $cpair | cut -s -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 -s -d ':' -f 1` if [[ "$remote" == "$ch"* ]]; then cl=`echo $cipair | cut -s -d ':' -f 2` [ ! -z "$cl" ] && ciph=$cl fi done fi if [ ! -z "$ciph" ]; then log using cipher $ciph ... fi if [ ! -d $data ]; then log no data directory ... exit -4 fi log backing up to $data ... today=`date -I` backupdir=$data/${user}_at_${host} cbd=$backupdir/$today 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 else lpb=$pb ob="$ob $pb" fi done if [ ! -d $cbd ]; then if [ ! -z "$lpb" ]; then cp -al $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 res=`"${rsync[@]}" 2>&1` ret=$? if [ "$ret" != "0" ]; then log backup terminated before completion ... log reason: log $res 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 -s -d ' ' -f 1-${numdel}`" 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