From d8f907a2765124162754386034fe6ede5032d799 Mon Sep 17 00:00:00 2001 From: Adam Weinberger Date: Fri, 14 Jun 2019 14:58:50 -0600 Subject: [PATCH] Make the number of each backup type configurable (#31) A value of 0 means to keep indefinitely. --- README.md | 7 +++--- acts | 63 +++++++++++++++++++++++++----------------------- acts.conf.sample | 7 ++++++ 3 files changed, 44 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index f379c47..2c8fb8d 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,9 @@ design goals: - Calendar-based backup schedule - Portable, small, code footprint. -One Tarsnap archive is created per-target per-run. 31 daily, 12 monthly, -and indefinite yearly backups are kept. +One Tarsnap archive is created per-target per-run. By default, +31 daily and 12 monthly backups are kept, and yearly backups are +kept indefinitely. Download -------- @@ -40,7 +41,7 @@ Notes on behaviour: - If no monthly backup for the current month exists, create a monthly backup. - Otherwise, create a daily backup. -- Archives are deleted using the following logic: +- Archives are deleted using the following logic by default: - If any backups failed, delete nothing. - Keep the most recent 31 daily backups, and delete any older ones. diff --git a/acts b/acts index 9cad21f..683ff29 100755 --- a/acts +++ b/acts @@ -97,6 +97,9 @@ postbackupscript="${postbackupscript=}" tarsnap="${tarsnap:=tarsnap}" tarsnapbackupoptions="${tarsnapbackupoptions=}" lockfile="${lockfile=/var/run/acts}" +dailybackups="${dailybackups:=31}" +monthlybackups="${monthlybackups:=12}" +yearlybackups="${yearlybackups:=0}" LANG="${LANG=en_US.UTF-8}" export LANG @@ -113,6 +116,10 @@ else die "config-error message=\"invalid \$uselocaltime in acts.conf; valid options are 0 (for UTC) or 1 (for local time).\"" fi +[ $(( dailybackups )) = "$dailybackups" ] || die "config-error message=\"Invalid \$dailybackups; must be a number.\"" +[ $(( monthlybackups )) = "$monthlybackups" ] || die "config-error message=\"Invalid \$monthlybackups; must be a number.\"" +[ $(( yearlybackups )) = "$yearlybackups" ] || die "config-error message=\"Invalid \$yearlybackups; must be a number.\"" + # Create the lock. mkdir is atomic test/set, so use that instead of the typical test -f/touch combo if [ -d "$lockfile" ]; then die "acts-error message=\"$lockfile exists referencing PID $(cat "$lockfile/pid" 2>/dev/null || echo ""). Hint: If acts is not already running, rm -rf $lockfile.\"" @@ -191,40 +198,36 @@ if [ "$backuprc" != "0" ]; then die "acts-tarsnap-error One of the backups failed -- not deleting old backups" fi -for dir in $backuptargets; do - log_debug "message=\"Checking $dir for old backups to delete\"" - nicedirname=$(echo "$dir" | tr -d '/') - # We don't delete any yearly backups - - # We keep 12 monthly backups - monthlybackups=$(echo "$archives" | grep "$hostname-monthly-.+-$nicedirname$" | sort -rn) - if [ "$(echo "$monthlybackups" | wc -l)" -gt 12 ]; then - log_debug 'message="More than 12 monthly backups, deleting the oldest"' - echo "$monthlybackups" | tail -n +13 | while read -r archiveprefixtodel; do - log_verbose "message=\"Deleting backup prefix $archiveprefixtodel*\"" - echo "$archives" | grep -E "^$archiveprefixtodel" | while read -r archivetodel; do - log_debug "message=\"Deleting backup $archivetodel\"" - $tarsnap -d -f "$archivetodel" +prune_backups() { + backuplevel=$1 max=$2 + + if [ "$max" -gt 0 ]; then + backupslist=$(echo "$archives" | grep -E "$hostname-$backuplevel-.+-$nicedirname$" | sort -rn) + numberofbackups=$(echo "$backupslist" | awk 'END{print NR}') + if [ "$numberofbackups" -gt "$max" ]; then + log_debug "message=\"More than $max $backuplevel backups, deleting the oldest\"" + echo "$backupslist" | tail -n +"$(( max+1 ))" | while read -r archiveprefixtodel; do + log_verbose "message=\"Deleting backup prefix $archiveprefixtodel*\"" + echo "$archives" | grep -E "^$archiveprefixtodel" | while read -r archivetodel; do + log_debug "message=\"Deleting backup $archivetodel\"" + $tarsnap -d -f "$archivetodel" + done done - done + else + log_debug "message=\"Found $numberofbackups $backuplevel backups, not deleting\"" + fi else - log_debug "message=\"Found $(echo "$monthlybackups" | wc -l) monthly backups, not deleting\"" + log_debug "message=\"Keeping all $backuplevel backups indefinitely; not deleting any\"" fi +} - # We keep 31 daily backups - dailybackups=$(echo "$archives" | grep "$hostname-daily-.+-$nicedirname$" | sort -rn) - if [ "$(echo "$dailybackups" | wc -l)" -gt 31 ]; then - log_debug "message=\"More than 30 daily backups, deleting the oldest\"" - echo "$dailybackups" | tail -n +32 | while read -r archiveprefixtodel; do - log_verbose "message=\"Deleting backup prefix $archiveprefixtodel*\"" - echo "$archives" | grep -E "^$archiveprefixtodel" | while read -r archivetodel; do - log_debug "message=\"Deleting backup $archivetodel\"" - $tarsnap -d -f "$archivetodel" - done - done - else - log_debug "message=\"Found $(echo "$dailybackups" | wc -l) daily backups, not deleting any\"" - fi +for dir in $backuptargets; do + log_debug "message=\"Checking $dir for old backups to delete\"" + nicedirname=$(echo "$dir" | tr -d '/') + + prune_backups yearly $yearlybackups + prune_backups monthly $monthlybackups + prune_backups daily $dailybackups done # Run the post-backup script diff --git a/acts.conf.sample b/acts.conf.sample index 872bfc0..f5d0012 100644 --- a/acts.conf.sample +++ b/acts.conf.sample @@ -54,3 +54,10 @@ verbose=1 # Where acts should write its lockfile. # Default: /var/run/acts #lockfile=/tmp/acts + +# How many backups of each type to keep +# For all limits, 0 means keep indefinitely +# Defaults: 31 daily, 12 monthly, and yearly indefinitely +# dailybackups=31 +# monthlybackups=12 +# yearlybackups=0