Skip to content

Instantly share code, notes, and snippets.

@maxaudron
Last active November 7, 2021 15:09
Show Gist options
  • Save maxaudron/d8171a79c006e960b11668828cb6f376 to your computer and use it in GitHub Desktop.
Save maxaudron/d8171a79c006e960b11668828cb6f376 to your computer and use it in GitHub Desktop.
Make backups and clean up old ones using the grandfather-father-son principle
#!/bin/bash
# Make backups and clean up old ones using the grandfather-father-son principle
#
# Keeps one backup per four weeks ( roughly one per month ) for a year
# per week for four weeks
# per day for one week
#
# DRYRUN="yes" BACKUP_CONTEXT="/home/user" backup.sh BACKUP_SRC BACKUP_DEST
#
# DRYRUN: when set nothing is actually done, useful for testing
# BACKUP_CONTEXT: when set passes the variable to tar -C <>
#
# Required:
# BACKUP_SRC: path to back up, absolute, or relative to the current dir or $BACKUP_CONTEXT
# BACKUP_DEST: rclone specifier of where to put the backup: <remote>:<bucket>/<path>
set -o pipefail
BACKUP_NAME=${BACKUP_NAME:-"backup"}
backup_src="$1"
backup_dest="$2"
backup_ident=$(date +"%Y_%m_%d_%V_%u")
current_week=$(date +"%V")
current_year=$(date +"%Y")
current_quarter=$(date +"%q")
tmpdir=${TMPDIR:-"/tmp"}
do_backup() {
echo "making backup: ${BACKUP_NAME}_${backup_ident}"
if [ -z "$DRYRUN" ]; then
if [ -z "$BACKUP_CONTEXT" ]; then
tar -czf "${tmpdir}/${BACKUP_NAME}_${backup_ident}.tar.gz" -C "$BACKUP_CONTEXT" "$backup_src"
else
tar -czf "${tmpdir}/${BACKUP_NAME}_${backup_ident}.tar.gz" "$backup_src"
fi
rclone copy "${tmpdir}/${BACKUP_NAME}_${backup_ident}.tar.gz" "$backup_dest"
rm "${tmpdir}/${BACKUP_NAME}_${backup_ident}.tar.gz"
fi
}
list_backups() {
rclone lsf "${backup_dest}"
}
get_components() {
__SRC="$1"
__SRC="${__SRC##${BACKUP_NAME}_}"
__SRC="${__SRC%%.tar.gz}"
while IFS='_' read -ra COMP; do
WEEK="${COMP[3]}"
DAY_OF_WEEK="${COMP[4]}"
YEAR="${COMP[0]}"
done <<< "${__SRC}"
}
quarter() {
if [[ "$1" < "14" ]]; then
echo 1
elif (( $1 < 27 )); then
echo 2
elif (( $1 < 40 )); then
echo 3
else
echo 4
fi
}
delete_backup() {
echo "$1"
if [ -z "$DRYRUN" ]; then
rclone deletefile "${backup_dest}/$1"
fi
}
# Weeks to keep
# 04 08 12 16 20 24 28 32 36 40 44 48 52
#
# 01 02 03 |04 05 06 07 |08 09 10 11 |12 13
# 14 15 |16 17 18 19 |20 21 22 23 |24 25 26
# 27 |28 29 30 31 |32 33 34 35 |36 37 38 39
# |40 41 42 43 |44 45 46 47 |48 49 50 51 |52
#
weeks="04 08 12 16 20 24 28 32 36 40 44 48 52"
clean_backups() {
backups="$(list_backups)"
for backup in $backups; do
get_components "$backup"
if [[ "$YEAR" == "$current_year" ]]; then
if [[ "$WEEK" == "$current_week" ]]; then continue; fi
if [[ $DAY_OF_WEEK != 1 ]]; then
delete_backup "$backup"
continue
fi
if [[ $WEEK < $((current_week - 4)) ]]; then
if [[ "$weeks" != *"$WEEK"* ]]; then
delete_backup "$backup"
fi
if [[ "$(quarter $WEEK)" < "$((current_quarter - 2))" ]]; then
if [[ "04 16 28 40" != *"$WEEK"* ]]; then
delete_backup "$backup"
fi
fi
fi
elif [[ "$YEAR" == "$((current_year - 1))" ]]; then
if [[ $DAY_OF_WEEK != 1 ]]; then
delete_backup "$backup"
continue
fi
if [[ "$(quarter $WEEK)" > "$((current_quarter - 1))" ]]; then
if [[ "04 16 28 40" != *"$WEEK"* ]]; then
delete_backup "$backup"
fi
else
delete_backup "$backup"
fi
else
do_backup() {
echo "making backup: ${BACKUP_NAME}_${backup_ident}"
if [ -z "$DRYRUN" ]; then
if [ -z "$BACKUP_CONTEXT" ]; then
tar -czvf "${tmpdir}/${BACKUP_NAME}_${backup_ident}.tar.gz" -C "$BACKUP_CONTEXT" "$backup_src"
else
tar -czvf "${tmpdir}/${BACKUP_NAME}_${backup_ident}.tar.gz" "$backup_src"
fi
rclone copy "${tmpdir}/${BACKUP_NAME}_${backup_ident}.tar.gz" "$backup_dest"
rm "${tmpdir}/${BACKUP_NAME}_${backup_ident}.tar.gz"
fi
}
delete_backup "$backup"
fi
done
}
do_backup
clean_backups
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment