en:setup:backups:idtm-backup1.bash
idtm-backup1.bash
You can download this backup script and unzip it.
#!/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
