64 lines
1.8 KiB
Bash
64 lines
1.8 KiB
Bash
#!/usr/bin/env bash
|
|
# Delete only expired production-daily backup files. The prefix is fixed so a
|
|
# caller cannot aim this at manual recovery points or other files.
|
|
set -euo pipefail
|
|
|
|
prune_production_daily_backups() {
|
|
local directory="$1"
|
|
local retention_days="$2"
|
|
local now_epoch="${3:-}"
|
|
local dump name mtime age limit base verify verify_name
|
|
local -a doomed=()
|
|
|
|
[ -n "$directory" ] && [ -d "$directory" ] && [ ! -L "$directory" ] || {
|
|
echo "backup directory is unsafe" >&2
|
|
exit 1
|
|
}
|
|
[[ "$retention_days" =~ ^[1-9][0-9]{0,3}$ ]] || {
|
|
echo "retention days must be a positive integer" >&2
|
|
exit 1
|
|
}
|
|
if [ -z "$now_epoch" ]; then
|
|
now_epoch="$(date +%s)"
|
|
fi
|
|
[[ "$now_epoch" =~ ^[0-9]+$ ]] || {
|
|
echo "clock is unsafe" >&2
|
|
exit 1
|
|
}
|
|
limit=$((retention_days * 86400))
|
|
|
|
shopt -s nullglob
|
|
for dump in "$directory"/production-daily-*.dump.enc; do
|
|
name="$(basename -- "$dump")"
|
|
[[ "$name" =~ ^production-daily-[0-9]{8}T[0-9]{6}Z\.dump\.enc$ ]] || continue
|
|
[ -f "$dump" ] && [ ! -L "$dump" ] || continue
|
|
mtime="$(stat -c %Y "$dump" 2>/dev/null || stat -f %m "$dump")"
|
|
[[ "$mtime" =~ ^[0-9]+$ ]] || continue
|
|
age=$((now_epoch - mtime))
|
|
if (( age > limit )); then
|
|
doomed+=("$name")
|
|
fi
|
|
done
|
|
shopt -u nullglob
|
|
|
|
if ((${#doomed[@]} == 0)); then
|
|
return 0
|
|
fi
|
|
for name in "${doomed[@]}"; do
|
|
base="${name%.dump.enc}"
|
|
verify="$directory/${base}-restore-verify.json"
|
|
rm -f -- "$directory/$name"
|
|
if [ -e "$verify" ] && [ -f "$verify" ] && [ ! -L "$verify" ]; then
|
|
verify_name="$(basename -- "$verify")"
|
|
if [[ "$verify_name" =~ ^production-daily-[0-9]{8}T[0-9]{6}Z-restore-verify\.json$ ]]; then
|
|
rm -f -- "$verify"
|
|
fi
|
|
fi
|
|
printf '%s\n' "$name"
|
|
done
|
|
}
|
|
|
|
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
|
|
prune_production_daily_backups "${1:-}" "${2:-}" "${3:-}"
|
|
fi
|