Files
Jyotisha/deploy/prune-production-daily-backups.sh
T
jesse-uxandGrok (agent loop) 53d8df257d 给内测补上每日加密备份、宕机告警和日志上限。
主机安装和一次恢复演练留给产品。页面没有变化。

Co-Authored-By: Grok (agent loop)
2026-10-15 12:58:34 +08:00

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