Last active
November 7, 2021 15:09
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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