#!/bin/bash ## Create by Stefan Sterz in 2017 ## General Settings SOURCES=(/root /etc /home /boot) # What folder should be saved? TARGET="/home/sterzy/backup" # Where should they be saved? (absolute path!) EXCLUDEFROM="" # What files are supposed to be excluded? MAILADRESS="" # To which email adress should the logs be sent? LISTPACKAGES="" # Change to non empty string to save a list of # installed packages! LOG=$0.log # Log file name & location RSYNCCONF=(--delete) # Additional rsync flags ## SSH Settings TOSSH="" # What ssh server stores the backups? FROMSSH="" # From what ssh server should the files be # backuped? # For several reasons TOSSH and FROMSSH cannot # be used at the same time! TOSSHUSER="" # The ssh user of the system on which the # backup will be created TOSSHPORT=22 # The ssh port of the system on which the # backup will be created FROMSSHUSER="" # The ssh user of the system from which the # files will be backed up FROMSSHPORT=22 # The ssh port of the system from which the # files will be backed up WEEKS=5 # For how many weeks shall we save backups? ## Command variables, # These should be fine, but if something doesn't work these can be adjusted MOUNT="/bin/mount"; FGREP="/bin/fgrep"; SSH="/usr/bin/ssh"; EXPR="/usr/bin/expr" LN="/bin/ln"; ECHO="/bin/echo"; DATE="/bin/date"; MKDIR="/bin/mkdir" DPKG="/usr/bin/dpkg"; AWK="/usr/bin/awk"; MAIL="/usr/bin/mail" CUT="/usr/bin/cut"; TR="/usr/bin/tr"; RSYNC="/usr/bin/rsync" ## Helpers LAST="last"; INC="--link-dest=$TARGET/$LAST" # Format log information function formatLog () { while IFS= read -r line; do printf "$($DATE):\t$line\n" done } # Backup function # Creates a backup of the folders provides by $SOURCES in $TARGET in the sub # directory provided by the first parameter ($1) function backup () { $ECHO "Creating backup in \"$TOSSH:$TARGET$1\"..." 2>&1 | formatLog >> $LOG if [ -n "$LISTPACKAGES" ] && [ -z "$FROMSSH" ]; then $ECHO "$DPKG --get-selections | $AWK '!/deinstall|purge|hold/'|$CUT -f1 | $TR 'n' ' '" 2>&1 | formatLog >> $LOG $DPKG --get-selections | $AWK '!/deinstall|purge|hold/'|$CUT -f1 |$TR '\n' ' ' >> $LOG 2>&1 fi # Create folders that don't exist if [ -n "$S" ] && [ -n "$TOSSH" ] && [ -z "$FROMSSH" ]; then $ECHO "$S $TOSSH $MKDIR -p $TARGET$1" 2>&1 | formatLog >> $LOG $S $TOSSH "$MKDIR -p \"$TARGET\"$1" 2>&1 | formatLog >> $LOG 2>&1 if [ $? -ne 0 ]; then ERROR=1 fi elif ( [ -n "$S" ] && [ -n "$FROMSSH" ] && [ -z "$TOSSH" ] ) || ( [ -z "$S" ] ); then $ECHO "$MKDIR -p $TARGET$1" 2>&1 | formatLog >> $LOG $MKDIR -p "$TARGET"$1 2>&1 | formatLog >> $LOG 2>&1 if [ $? -ne 0 ]; then ERROR=1 fi fi # Backup files for SOURCE in "${SOURCES[@]}" do if [ -n "$S" ] && [ -n "$TOSSH" ] && [ -z "$FROMSSH" ]; then $ECHO "$RSYNC -e \"$S\" -avR \"$SOURCE\" ${RSYNCCONF[@]} \"$TOSSH:$TARGET$1\" $INC --exclude-from=\"$EXCLUDEFROM\"" 2>&1 | formatLog >> $LOG $RSYNC -e "$S" -avR "$SOURCE" "${RSYNCCONF[@]}" "$TOSSH:\"$TARGET\"$1" $INC --exclude-from="$EXCLUDEFROM" 2>&1 | formatLog >> $LOG 2>&1 if [ $? -ne 0 ]; then ERROR=1 fi elif [ -n "$S" ] && [ -z "$TOSSH" ] && [ -n "$FROMSSH" ]; then $ECHO "$RSYNC -e \"$S\" -avR \"$FROMSSH:$SOURCE\" ${RSYNCCONF[@]} $TARGET$1 $INC --exclude-from=\"$EXCLUDEFROM\"" 2>&1 | formatLog >> $LOG $RSYNC -e "$S" -avR "$FROMSSH:\"$SOURCE\"" "${RSYNCCONF[@]}" "$TARGET"$1 $INC --exclude-from="$EXCLUDEFROM" 2>&1 | formatLog >> $LOG 2>&1 if [ $? -ne 0 ]; then ERROR=1 fi elif [-z "$S"] && [ -z "$TOSSH" ] && [ -z "$FROMSSh" ]; then $ECHO "$RSYNC -avR \"$SOURCE\" ${RSYNCCONF[@]} $TARGET$1 $INC --exclude-from=\"$EXCLUDEFROM\"" 2>&1 | formatLog >> $LOG $RSYNC -avR "$SOURCE" "${RSYNCCONF[@]}" "$TARGET"$1 $INC --exclude-from="$EXCLUDEFROM" 2>&1 | formatLog >> $LOG 2>&1 if [ $? -ne 0 ]; then ERROR=1 fi fi done # Create a link to the latest backup if [ -n "$S" ] && [ -n "$TOSSH" ] && [ -z "$FROMSSH" ]; then $ECHO "$S $TOSSH $LN -nsf $TARGET$1 $TARGET$LAST" 2>&1 | formatLog >> $LOG $S $TOSSH "$LN -nsf \"$TARGET\"$1 \"$TARGET\"$LAST" 2>&1 | formatLog >> $LOG 2>&1 if [ $? -ne 0 ]; then ERROR=1 fi elif ( [ -n "$S" ] && [ -n "$FROMSSH" ] && [ -z "$TOSSH" ] ) || ( [ -z "$S" ] ); then $ECHO "$LN -nsf $TARGET$1 $TARGET$LAST" 2>&1 | formatLog >> $LOG $LN -nsf "$TARGET"$1 "$TARGET"$LAST 2>&1 | formatLog >> $LOG 2>&1 if [ $? -ne 0 ]; then ERROR=1 fi fi $ECHO "Done creating backup in \"$TOSSH:$TARGET$1\"" 2>&1 | formatLog >> $LOG } # Clear log $ECHO -n "" > $LOG # Make sure the provided path is absolute if [ "${TARGET:${#TARGET}-1:1}" != "/" ]; then TARGET=$TARGET/ fi # Handle SSH info if [ -n "$TOSSH" ] && [ -z "$FROMSSH" ]; then S="$SSH -p $TOSSHPORT -l $TOSSHUSER" elif [ -z "$TOSSH" ] && [ -n "$FROMSSH" ]; then S="$SSH -p $FROMSSHPORT -l $FROMSSHUSER" elif [ -n "$TOSSH" ] && [ -n "$FROMSSH" ]; then ERROR=1 $ECHO "Plese don't provide to and from ssh information!" 2>&1 | formatLog >> $LOG $ECHO "No backup performed!" 2>&1 | formatLog >> $LOG exit 1 fi # Get date etc. WEEKDAY=$($DATE +"%u") # %a = weekday as number DAY=$($DATE +"%d") # %d = day in month as number MONTH=$($DATE +%m) # %m = month as number HOUR=$($DATE +"%H") # %H = hour as number WEEK=$($EXPR $($DATE +"%W") % $WEEKS) # %W = week as number, used to save backups for the past $WEEKS weeks # Create a backup every first day in a month if [[ $DAY = 01 ]]; then backup "monthly/$MONTH-$($DATE +"%B")" fi # Create a special backup approx every week if [[ $WEEKDAY = 7 ]]; then backup "weekly/$WEEK" fi # Create daily backups backup "daily/$WEEKDAY-$($DATE +"%A")/$HOUR" # Send email if an adress was provided if [ -n "$MAILADRESS" ]; then if [ $ERROR ]; then $MAIL -s "[Backup] error occured during backup - $LOG" $MAILADRESS < $LOG else $MAIL -s "[Backup] backup created successfully - $LOG" $MAILADRESS < $LOG fi fi