forgejo: modify backups pruning retention

Signed-off-by: David Kirwan <davidkirwanirl@gmail.com>
This commit is contained in:
David Kirwan
2026-01-29 15:39:21 +00:00
parent 0f1dbc8094
commit b5da9bfcc7

View File

@@ -1,91 +1,122 @@
#!/bin/bash
# Backup management script configuration
BACKUP_DIR="/root/ocp4/openshift-apps/forgejo/backups/dump/" # Where backups are stored
DAILY_RETENTION=7 # Keep 7 daily backups
BACKUP_DIR="/root/ocp4/openshift-apps/forgejo/backups/dump/"
LOG_FILE="/root/ocp4/openshift-apps/forgejo/backups/log/forgejo_backup_prune.log"
# Logging function
# Retention settings - how many backups to keep at each tier
DAILY_RETENTION=2 # Keep 2 daily backups
WEEKLY_RETENTION=0 # Keep 0 weekly backups
MONTHLY_RETENTION=0 # Keep 0 monthly backups
YEARLY_RETENTION=0 # Keep 0 yearly backups
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}
# Prune backups of a given tier, keeping only the N most recent
# Usage: prune_tier "pattern" retention_count "tier_name"
prune_tier() {
local pattern="$1"
local retention="$2"
local tier="$3"
[[ $retention -lt 0 ]] && retention=0
local backups=$(find "$BACKUP_DIR" -name "$pattern" -printf "%T@ %p\n" 2>/dev/null | sort -nr | cut -d' ' -f2)
local count=$(echo "$backups" | grep -c . 2>/dev/null || echo 0)
if [[ $count -gt $retention ]]; then
echo "$backups" | tail -n +$((retention + 1)) | xargs -r rm -f
log "Pruned $tier backups: kept $retention of $count"
fi
}
# Ensure backup directory exists
mkdir -p "$BACKUP_DIR"
# Check if script is run as root
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root"
exit 1
fi
# Start pruning process
log "Starting backup pruning process"
# Step 1: Keep the last 7 daily backups
find "$BACKUP_DIR" -name "forgejo-dump-*.zip" -mtime +"$DAILY_RETENTION" -not -name "weekly*" -not -name "monthly*" -not -name "yearly*" -delete
if [[ $? -eq 0 ]]; then
log "Pruned daily backups older than ${DAILY_RETENTION} days"
else
log "Error pruning daily backups"
# Step 1: Prune daily backups with size protection
DAILY_BACKUPS=$(find "$BACKUP_DIR" -name "forgejo-dump-*.zip" -printf "%T@ %p\n" | sort -nr | cut -d' ' -f2)
DAILY_COUNT=$(echo "$DAILY_BACKUPS" | grep -c . 2>/dev/null || echo 0)
if [[ $DAILY_COUNT -gt $DAILY_RETENTION ]]; then
LATEST_BACKUP=$(echo "$DAILY_BACKUPS" | head -n 1)
LATEST_SIZE=$(stat -c%s "$LATEST_BACKUP" 2>/dev/null || echo 0)
# Find the largest older backup
LARGEST_OLDER=""
LARGEST_OLDER_SIZE=0
while read -r backup; do
[[ -z "$backup" ]] && continue
SIZE=$(stat -c%s "$backup" 2>/dev/null || echo 0)
if [[ $SIZE -gt $LARGEST_OLDER_SIZE ]]; then
LARGEST_OLDER_SIZE=$SIZE
LARGEST_OLDER="$backup"
fi
done <<< "$(echo "$DAILY_BACKUPS" | tail -n +2)"
# Protect largest if latest is suspiciously small
PROTECT=""
if [[ $LATEST_SIZE -lt $LARGEST_OLDER_SIZE && -n "$LARGEST_OLDER" ]]; then
PROTECT="$LARGEST_OLDER"
log "WARNING: Latest backup ($LATEST_SIZE bytes) smaller than largest ($LARGEST_OLDER_SIZE bytes)"
log "Protecting: $LARGEST_OLDER"
fi
# Delete old backups, protecting the largest if needed
KEPT=0
while read -r backup; do
[[ -z "$backup" ]] && continue
if [[ $KEPT -lt $DAILY_RETENTION ]]; then
((KEPT++))
elif [[ "$backup" == "$PROTECT" ]]; then
log "Kept protected: $(basename "$backup")"
else
rm -f "$backup"
log "Deleted: $(basename "$backup")"
fi
done <<< "$DAILY_BACKUPS"
fi
# Step 2: Weekly backup (run on Sundays)
if [[ $(date +%u) -eq 7 ]]; then
# Find the latest daily backup from this week
LATEST_DAILY=$(find "$BACKUP_DIR" -name "forgejo-dump-*.zip" -not -name "weekly*" -not -name "monthly*" -not -name "yearly*" -printf "%T@ %p\n" | sort -nr | head -n 1 | cut -d' ' -f2)
if [[ -n "$LATEST_DAILY" ]]; then
EPOCH=$(basename "$LATEST_DAILY" | grep -o '[0-9]\{10,\}')
WEEK_NUM=$(date +%U)
NEW_NAME="weekly${WEEK_NUM}-forgejo-dump-${EPOCH}.zip"
cp "$LATEST_DAILY" "${BACKUP_DIR}/${NEW_NAME}"
log "Created weekly backup: ${NEW_NAME}"
# Prune other daily backups from this week
WEEK_START=$(date -d "last Sunday" +%s)
find "$BACKUP_DIR" -name "forgejo-dump-*.zip" -not -name "weekly*" -not -name "monthly*" -not -name "yearly*" -exec sh -c '[[ $(echo $(basename "{}") | grep -o "[0-9]\{10,\}") -ge '"$WEEK_START"' ]]' \; -delete
log "Pruned other daily backups for week ${WEEK_NUM}"
else
log "No daily backup found for weekly processing"
# Step 2-4: Tiered backups (only if retention > 0)
# Weekly promotion (Sundays)
if [[ $WEEKLY_RETENTION -gt 0 && $(date +%u) -eq 7 ]]; then
LATEST=$(find "$BACKUP_DIR" -name "forgejo-dump-*.zip" -printf "%T@ %p\n" | sort -nr | head -n1 | cut -d' ' -f2)
if [[ -n "$LATEST" ]]; then
EPOCH=$(basename "$LATEST" | grep -o '[0-9]\{10,\}')
cp "$LATEST" "${BACKUP_DIR}/weekly$(date +%U)-forgejo-dump-${EPOCH}.zip"
log "Created weekly backup"
fi
prune_tier "weekly*-forgejo-dump-*.zip" "$WEEKLY_RETENTION" "weekly"
fi
# Step 3: Monthly backup (run on last day of the month)
if [[ $(date -d tomorrow +%d) -eq 1 ]]; then
# Find the latest weekly backup
LATEST_WEEKLY=$(find "$BACKUP_DIR" -name "weekly*-forgejo-dump-*.zip" -not -name "monthly*" -not -name "yearly*" -printf "%T@ %p\n" | sort -nr | head -n 1 | cut -d' ' -f2)
if [[ -n "$LATEST_WEEKLY" ]]; then
EPOCH=$(basename "$LATEST_WEEKLY" | grep -o '[0-9]\{10,\}')
MONTH_NUM=$(date +%m)
NEW_NAME="monthly${MONTH_NUM}-forgejo-dump-${EPOCH}.zip"
cp "$LATEST_WEEKLY" "${BACKUP_DIR}/${NEW_NAME}"
log "Created monthly backup: ${NEW_NAME}"
# Prune other weekly backups
find "$BACKUP_DIR" -name "weekly*-forgejo-dump-*.zip" -not -name "monthly*" -not -name "yearly*" -delete
log "Pruned other weekly backups"
else
log "No weekly backup found for monthly processing"
# Monthly promotion (last day of month)
if [[ $MONTHLY_RETENTION -gt 0 && $(date -d tomorrow +%d) -eq 1 ]]; then
LATEST=$(find "$BACKUP_DIR" -name "weekly*-forgejo-dump-*.zip" -printf "%T@ %p\n" | sort -nr | head -n1 | cut -d' ' -f2)
if [[ -n "$LATEST" ]]; then
EPOCH=$(basename "$LATEST" | grep -o '[0-9]\{10,\}')
cp "$LATEST" "${BACKUP_DIR}/monthly$(date +%m)-forgejo-dump-${EPOCH}.zip"
log "Created monthly backup"
fi
prune_tier "monthly*-forgejo-dump-*.zip" "$MONTHLY_RETENTION" "monthly"
fi
# Step 4: Yearly backup (run on last day of the year)
if [[ $(date -d tomorrow +%j) -eq 1 ]]; then
# Find the latest monthly backup
LATEST_MONTHLY=$(find "$BACKUP_DIR" -name "monthly*-forgejo-dump-*.zip" -not -name "yearly*" -printf "%T@ %p\n" | sort -nr | head -n 1 | cut -d' ' -f2)
if [[ -n "$LATEST_MONTHLY" ]]; then
EPOCH=$(basename "$LATEST_MONTHLY" | grep -o '[0-9]\{10,\}')
YEAR=$(date +%Y)
NEW_NAME="yearly${YEAR}-forgejo-dump-${EPOCH}.zip"
cp "$LATEST_MONTHLY" "${BACKUP_DIR}/${NEW_NAME}"
log "Created yearly backup: ${NEW_NAME}"
# Prune other monthly backups
find "$BACKUP_DIR" -name "monthly*-forgejo-dump-*.zip" -not -name "yearly*" -delete
log "Pruned other monthly backups"
else
log "No monthly backup found for yearly processing"
# Yearly promotion (last day of year)
if [[ $YEARLY_RETENTION -gt 0 && $(date -d tomorrow +%j) -eq 1 ]]; then
LATEST=$(find "$BACKUP_DIR" -name "monthly*-forgejo-dump-*.zip" -printf "%T@ %p\n" | sort -nr | head -n1 | cut -d' ' -f2)
if [[ -n "$LATEST" ]]; then
EPOCH=$(basename "$LATEST" | grep -o '[0-9]\{10,\}')
cp "$LATEST" "${BACKUP_DIR}/yearly$(date +%Y)-forgejo-dump-${EPOCH}.zip"
log "Created yearly backup"
fi
prune_tier "yearly*-forgejo-dump-*.zip" "$YEARLY_RETENTION" "yearly"
fi
log "Backup pruning process completed"