User Tools

Site Tools


en:setup:backups:idtm-backup1.bash

idtm-backup1.bash

You can download this backup script and unzip it.

idtm-backup1.bash.zip

#!/bin/bash

# http://www.noah.org/engineering/src/shell/rsync_backup
# https://digitalis.io/blog/technology/incremental-backups-with-rsync-and-hard-links/
# https://linuxconfig.org/how-to-create-incremental-backups-using-rsync-on-linux
# https://www.perfacilis.com/blog/systeembeheer/linux/incremental-back-up-script-using-rsync.html


# The source path to the folder we want to backup.
SOURCE_DIR="/home/idtm/IDTM-Library"
# The destination path to the external backup drive
DESTINATION_BASE="/media/idtm/IDTM-Backup1/IDTM-Server/IDTM-Library"
# Get the current date and time
DATETIME="$(date '+%Y-%m-%d_%H%M%S')"
# Set the path for today's backup
BACKUP_PATH="${DESTINATION_BASE}/${DATETIME}"
LATEST_LINK="${DESTINATION_BASE}/latest"
# Set where weekly backups are stored
DESTINATION_BASE_WEEKLY="/media/idtm/IDTM-Backup1/IDTM-Server/IDTM-Library/weekly"
# Set where monthly backups are stored
DESTINATION_BASE_MONTHLY="/media/idtm/IDTM-Backup1/IDTM-Server/IDTM-Library/monthly"

PERMS_DIR=755
PERMS_FILE=644
NORMALIZE_PERMS=true

# set minimum number of seconds between backups
INTERVAL=3000 # default is 3000 (one hour = 3600 seconds)
# set how many seconds to keep daily backups
KEEP_DAILY_FOR_THIS_LONG=604800 # one week = 604800 seconds

# create a "latest" directory if it doesn't exist
prepare_backup_dir() {
   if [ ! -d $LATEST_LINK ]; then
      mkdir -p $LATEST_LINK
      touch -d "January 1 2000" $LATEST_LINK
   fi
}

# exit this script if not enough time has passed since last backup
check_interval() {
   local LAST=$(stat -c %Y $LATEST_LINK)
   local NOW=$(date +%s)
   local ELAPSED=$(($NOW - $LAST))
   
   if [ "$ELAPSED" -lt "$INTERVAL" ]; then
      echo "Last backup was ${ELAPSED}s ago, which is less than ${INTERVAL}s."
      exit
   fi
}

perform_backup() {
   rsync -av --delete --exclude="lost+found" \
     "${SOURCE_DIR}/" \
     --link-dest "${LATEST_LINK}" \
      "${BACKUP_PATH}"

   rm -rf "${LATEST_LINK}"
   echo "ln -s ${BACKUP_PATH} ${LATEST_LINK}"
   ln -s "${BACKUP_PATH}" "${LATEST_LINK}"
   touch "${BACKUP_PATH}"

# normalize permissions to reduce access problems later
   if [ "$NORMALIZE_PERMS" = true ]; then
      echo "normalize permissions"
      find $LATEST_LINK -type d -exec chmod $PERMS_DIR {} \;
      find $LATEST_LINK -type f -exec chmod $PERMS_FILE {} \;
   fi
}

verify_days() {
   local STAT_AGE=0
   local NOW=$(date +%s)
   local ELAPSED=0
   
   # loop through each backup folder
   for f in $DESTINATION_BASE/* ; do
      BASENAME="$(basename $f)"
      # check if it is a directory
      if [ -d "${f}" ]; then
         # exclude latest, weekly, and monthly
         if [[ "$BASENAME" != "latest" && "$BASENAME" != "weekly" && "$BASENAME" != "monthly" ]]; then
            # get age of the file in seconds
            STAT_AGE=$(stat -c %Y $f)
            ELAPSED=$(($NOW - $STAT_AGE))
            echo "The age of $f is $ELAPSED seconds"
            # delete daily backups older than KEEP_DAILY_FOR_THIS_LONG seconds ago
            if [ "$ELAPSED" -ge "$KEEP_DAILY_FOR_THIS_LONG" ]; then
               rm -rf $f
            fi
         fi
      fi
   done
}

verify_weeks() {
   local NOW=$(date +%s)
   local WEEKS_SECS_ELAPSED=0
   local F_AGE=0
   # how many weeks to keep backups
   local WEEKS_LIMIT=6
   local WEEKS_LIMIT_SECS=$(( 604800*$WEEKS_LIMIT ))
   
   # get the current week number of this year
   local THIS_WEEK="$(date +%U)";
   
   # get the current year number of this year
   local THIS_YEAR="$(date +%y)";
   
   # get the latest previous weekly backup
   local LATEST_WEEKLY="$(ls -tr $DESTINATION_BASE_WEEKLY | tail -1)"
   local AGE_LATEST_WEEKLY="$(stat -c %Y $DESTINATION_BASE_WEEKLY/$LATEST_WEEKLY)"
   local WEEK_NUMBER_LATEST_WEEKLY="$(date --date=@$AGE_LATEST_WEEKLY +%U)"
   local YEAR_NUMBER_LATEST_WEEKLY="$(date --date=@$AGE_LATEST_WEEKLY +%y)"
   # make another week backup if there isn't a backup for this week number yet
   if [ "$WEEK_NUMBER_LATEST_WEEKLY" -lt "$THIS_WEEK" ] || \
      [ "$YEAR_NUMBER_LATEST_WEEKLY" -lt "$THIS_YEAR" ] || \
      [ -z "$LATEST_WEEKLY" ] ; then
      cp -al "${BACKUP_PATH}" "$DESTINATION_BASE_WEEKLY/$DATETIME"
      echo "Weekly backup made: $DESTINATION_BASE_WEEKLY/$DATETIME"
   fi

   # clean up weeks older than WEEKS_OLD weeks
   for f in $DESTINATION_BASE_WEEKLY/* ; do
      BASENAME="$(basename $f)"
      # check if it is a directory
      if [ -d "${f}" ]; then
         F_AGE="$(stat -c %Y $f)"
         WEEKS_SECS_ELAPSED=$(($NOW - $F_AGE))
         # delete weekly backups older than WEEKS_LIMIT weeks ago
         if [ $WEEKS_SECS_ELAPSED -ge $WEEKS_LIMIT_SECS ]; then
            rm -rf $f
         fi
      fi
   done
}

verify_months() {
   # get the current month number of this year
   local THIS_MONTH="$(date +%m)";
   local THIS_YEAR="$(date +%y)";
   # get the latest previous monthly backup
   local LATEST_MONTHLY="$(ls -tr $DESTINATION_BASE_MONTHLY | tail -1)"
   local AGE_LATEST_MONTHLY="$(stat -c %Y $DESTINATION_BASE_MONTHLY/$LATEST_MONTHLY)"
   local MONTH_NUMBER_LATEST_MONTHLY="$(date --date=@$AGE_LATEST_MONTHLY +%m)"
   local YEAR_NUMBER_LATEST_MONTHLY="$(date --date=@$AGE_LATEST_MONTHLY +%y)"
   # copy another month if there isn't a backup for this mmonth number yet
   if [ "$MONTH_NUMBER_LATEST_MONTHLY" -lt "$THIS_MONTH" ] || \
      [ "$YEAR_NUMBER_LATEST_MONTHLY" -lt "$THIS_YEAR" ] || \
      [ -z "$LATEST_MONTHLY" ] ; then
      cp -al "${BACKUP_PATH}" "$DESTINATION_BASE_MONTHLY/$DATETIME"
      echo "Monthly backup made: $DESTINATION_BASE_MONTHLY/$DATETIME"
   fi
}

main () {
   prepare_backup_dir
   check_interval
   perform_backup
   verify_days
   verify_weeks
   verify_months
}

main
en/setup/backups/idtm-backup1.bash.txt · Last modified: by 127.0.0.1

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki