diff --git a/gaboshlib/g_backup.bashfunc b/gaboshlib/g_backup.bashfunc new file mode 100644 index 0000000..96ff816 --- /dev/null +++ b/gaboshlib/g_backup.bashfunc @@ -0,0 +1,111 @@ +#!/bin/bash + +function g_backup { + + #### Config defaults + # dir(s) to backup (: separated) + BACKUPDIRS=/"" + # Excludefile für rsync + BACKUPEXCLUDES="" + # Backup-Server (Backup-Destination) + BACKUPSRV="" + # SSH Port + BACKUPSRVPORT="22" + # SSH User + BACKUPSRVUSER="root" + # Destination path on Backup-Server + BACKUPSRVPATH="" + # run optional command on server and start backup only on success + BACKUPSRVTESTCMD="" + # Copy only without hostname/backup-date Structure + NODIRSTRUCT="" + + g_tries=3 + g_tries_delay=1 + + # Config files for custom vars + [ -r /usr/local/etc/g_backup.conf ] && . /usr/local/etc/g_backup.conf + [ -r ~/.config/g_backup.conf ] && . ~/.config/g_backup.conf + + # Use CMD-line args + [ -n "$1" ] && BACKUPDIRS=$1 + [ -n "$2" ] && BACKUPSRVPATH=$2 + [ -n "$3" ] && BACKUPEXCLUDES=$3 + [ -n "$4" ] && BACKUPSRV=$4 + [ -n "$5" ] && BACKUPSRVPORT=$5 + [ -n "$6" ] && BACKUPSRVUSER=$6 + [ -n "$7" ] && BACKUPSRVTESTCMD=$7 + [ -n "$8" ] && NODIRSTRUCT=$8 + + usage=" + $0 BACKUPDIR1[:BACKUPDIR2:BACKUPDIR3] BACKUPPATH [BACKUPEXCLUDES BACKUPSRV BACKUPSRVPORT BACKUPSRVUSER BACKUPSRVTESTCMD NODIRSTRUCT]" + + [ -z "$BACKUPDIRS" ] && g_echo_error_exit "No Directory to Backup (BACKUPDIR) given $usage" + [ -z "$BACKUPSRVPATH" ] && g_echo_error_exit "No path to put the Backup (BACKUPPATH) given $usage" + + if [ -n "$BACKUPSRV" ] + then + [ -z "$BACKUPSRVPORT" ] && g_echo_error_exit "No SSH-Port given $usage" + sshopts="g_retrycmd ssh -p $BACKUPSRVPORT -o BatchMode=yes -o StrictHostKeyChecking=accept-new $BACKUPSRVUSER@$BACKUPSRV" + fi + + rsyncopts="-aXAh --delete" + [ -n "$BACKUPEXCLUDES" ] && rsyncopts="$rsyncopts --delete-excluded --exclude-from=$BACKUPEXCLUDES" + [ -n "$BACKUPSRV" ] && rsyncopts="$rsyncopts -e \\'ssh -p $BACKUPSRVPORT\\'" + + ORIGIFS="$IFS" + IFS=':' + # Prepare Dest-Dir on Backup-Server + CMDS="mkdir -p ${BACKUPSRVPATH}:chmod 700 ${BACKUPSRVPATH}" + [ -n "$BACKUPSRVTESTCMD" ] && CMDS="$BACKUPSRVTESTCMD:$CMDS" + for CMD in $CMDS + do + IFS="$ORIGIFS" + g_runcmd $sshopts $CMD || exit $? + done + + IFS=':' + for BACKUPDIR in $BACKUPDIRS + do + IFS="$ORIGIFS" + rsyncoptsrun=$rsyncopts + + # prepare paths + if [ -z "$NODIRSTRUCT" ] + then + # build structure + BACKUPSRVPATH_WITH_HOST="$BACKUPSRVPATH/$(hostname)" + BACKUPSRVPATH_WITH_DATE="$BACKUPSRVPATH_WITH_HOST/backup-$(date +%Y-%m-%d)/$BACKUPDIR" + BACKUPSRVPATH_WITH_DATE_INCOMPLETE="$BACKUPSRVPATH_WITH_DATE-incomplete" + g_runcmd $sshopts "mkdir -p $BACKUPSRVPATH_WITH_DATE_INCOMPLETE" || exit $? + BACKUPSRVPATH_LINK_DEST="$($sshopts ls -d $BACKUPSRVPATH_WITH_HOST/backup-*/$BACKUPDIR 2>/dev/null | grep -v \\' Try \\' | tail -n1)" + # linkdest + [ -n "$BACKUPSRVPATH_LINK_DEST" ] && rsyncoptsrun="$rsyncoptsrun --link-dest=$BACKUPSRVPATH_LINK_DEST" + else + BACKUPSRVPATH_WITH_DATE_INCOMPLETE="/$BACKUPSRVPATH" + fi + + # Backup + [ -n "$BACKUPSRV" ] && sshrsync="$BACKUPSRVUSER@$BACKUPSRV:" + echo "g_retrycmd rsync $rsyncoptsrun $BACKUPDIR/ ${sshrsync}$BACKUPSRVPATH_WITH_DATE_INCOMPLETE/" >$g_tmp/bcmd + g_echo "Running Backup $BACKUPDIR with +$(cat $g_tmp/bcmd)" + g_runcmd bash $g_tmp/bcmd || exit $? + + # done if no direstructure + [ -n "$NODIRSTRUCT" ] && continue + + g_runcmd $sshopts test -e $BACKUPSRVPATH_WITH_DATE && $sshopts mv $BACKUPSRVPATH_WITH_DATE $BACKUPSRVPATH_WITH_DATE-$$-old + g_runcmd $sshopts mv $BACKUPSRVPATH_WITH_DATE_INCOMPLETE $BACKUPSRVPATH_WITH_DATE || exit $? + + # Cleanup old backups + yearmonth="$(date +%Y-%m-)" + yearmonthbefore="$(date +%Y-%m- --date='-1 month')" + echo "$sshopts find $BACKUPSRVPATH_WITH_HOST -mindepth 1 -maxdepth 1 -type d -name \"backup-*\" | egrep -v \"backup-$yearmonth|backup-$yearmonthbefore|backup-20[0-9][0-9]-[0-9][0-9]-01\" | xargs -r rm -r" >>$g_tmp/bcmd + g_echo "Cleaning up Backupdir $BACKUPDIR with '$(cat $g_tmp/bcmd)'" + g_runcmd bash $g_tmp/bcmd || exit $? + + done + + g_echo "Backup-Skript beendet" +}