#!/usr/bin/env bash # rotate_backups — retention policy estilo rsnapshot (daily/weekly/monthly) rotate_backups() { local dir="$1" local new_file="$2" local daily=7 local weekly=4 local monthly=12 # Parsear args posicionales o key=value local i=3 for arg in "${@:3}"; do case "$arg" in daily=*) daily="${arg#daily=}" ;; weekly=*) weekly="${arg#weekly=}" ;; monthly=*) monthly="${arg#monthly=}" ;; *) case $i in 3) daily="$arg" ;; 4) weekly="$arg" ;; 5) monthly="$arg" ;; esac ;; esac i=$((i + 1)) done # Validar numericos if ! [[ "$daily" =~ ^[0-9]+$ ]] || ! [[ "$weekly" =~ ^[0-9]+$ ]] || ! [[ "$monthly" =~ ^[0-9]+$ ]]; then echo "ERROR: daily, weekly y monthly deben ser enteros positivos" >&2 return 3 fi # Validar new_file if [[ ! -e "$new_file" ]]; then echo "ERROR: new_file no existe: $new_file" >&2 return 1 fi # Crear directorio si no existe if ! mkdir -p "$dir" 2>/dev/null; then echo "ERROR: no se pudo crear el directorio: $dir" >&2 return 2 fi local dow dow=$(date +%w) # 0=domingo local dom dom=$(date +%d) # 01-31 local rotated_daily=0 local rotated_weekly=0 local rotated_monthly=0 # --- Monthly: si dia 1, rotar desde weekly. ANTES de borrar --- if [[ "$dom" == "01" ]] && (( monthly > 0 )); then local weekly_src="$dir/weekly.$((weekly - 1))" if [[ -e "$weekly_src" ]]; then # Borrar monthly mas viejo local oldest_monthly="$dir/monthly.$((monthly - 1))" [[ -e "$oldest_monthly" ]] && rm -rf "$oldest_monthly" # Desplazar monthly. → monthly. for (( j = monthly - 2; j >= 0; j-- )); do [[ -e "$dir/monthly.$j" ]] && mv "$dir/monthly.$j" "$dir/monthly.$((j+1))" done cp -a "$weekly_src" "$dir/monthly.0" rotated_monthly=1 fi fi # --- Weekly: si domingo, rotar desde daily. ANTES de borrarlo --- if [[ "$dow" == "0" ]] && (( weekly > 0 )); then local daily_src="$dir/daily.$((daily - 1))" if [[ -e "$daily_src" ]]; then # Borrar weekly mas viejo local oldest_weekly="$dir/weekly.$((weekly - 1))" [[ -e "$oldest_weekly" ]] && rm -rf "$oldest_weekly" # Desplazar weekly. → weekly. for (( j = weekly - 2; j >= 0; j-- )); do [[ -e "$dir/weekly.$j" ]] && mv "$dir/weekly.$j" "$dir/weekly.$((j+1))" done cp -a "$daily_src" "$dir/weekly.0" rotated_weekly=1 fi fi # --- Daily: borrar el mas viejo, desplazar, mover new_file a daily.0 --- local oldest_daily="$dir/daily.$((daily - 1))" [[ -e "$oldest_daily" ]] && rm -rf "$oldest_daily" for (( j = daily - 2; j >= 0; j-- )); do [[ -e "$dir/daily.$j" ]] && mv "$dir/daily.$j" "$dir/daily.$((j+1))" done mv "$new_file" "$dir/daily.0" rotated_daily=1 # Contar slots ocupados para el reporte local cnt_daily=0 cnt_weekly=0 cnt_monthly=0 for (( j = 0; j < daily; j++ )); do [[ -e "$dir/daily.$j" ]] && cnt_daily=$((cnt_daily + 1)); done for (( j = 0; j < weekly; j++ )); do [[ -e "$dir/weekly.$j" ]] && cnt_weekly=$((cnt_weekly + 1)); done for (( j = 0; j < monthly; j++ )); do [[ -e "$dir/monthly.$j" ]] && cnt_monthly=$((cnt_monthly + 1)); done echo "ROTATED daily=$cnt_daily weekly=$cnt_weekly monthly=$cnt_monthly dir=$dir" }