Merge pull request 'Fix: Backup-Script mit smarter Rotation und Lock-Schutz gegen parallele Läufe' (#32) from fds2610-bot/Steuerkram:main into main
Reviewed-on: https://codeberg.org/fds2610/Steuerkram/pulls/32
This commit is contained in:
commit
6285e1c087
2 changed files with 93 additions and 10 deletions
|
|
@ -2,6 +2,15 @@
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 2026-04-12 – Backup: smarte Rotation und Lock-Schutz
|
||||||
|
|
||||||
|
### Geändert
|
||||||
|
- `scripts/backup.sh`: Rotation auf 7 Tages- / 4 Wochen- / 12 Monats-Buckets umgestellt (statt pauschaler 90-Tage-Löschung)
|
||||||
|
- `scripts/backup.sh`: `flock`-Lock verhindert parallele Läufe bei Verzögerungen
|
||||||
|
- `scripts/backup.sh`: Pfade sind absolut (Script funktioniert auch aus Cron ohne Verzeichniswechsel)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 2026-04-12 – Uploads: named Volume → Bind Mount
|
## 2026-04-12 – Uploads: named Volume → Bind Mount
|
||||||
|
|
||||||
### Geändert
|
### Geändert
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,37 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Steuerkram – Backup-Script
|
# Steuerkram – Backup-Script mit smarter Rotation
|
||||||
# GoBD: Datensicherung muss regelmäßig erfolgen.
|
# GoBD: Datensicherung muss regelmäßig erfolgen.
|
||||||
# Usage: ./scripts/backup.sh
|
# Usage: ./scripts/backup.sh
|
||||||
|
#
|
||||||
|
# Retention:
|
||||||
|
# - letzte 7 Tage: täglich (ein Backup pro Tag)
|
||||||
|
# - Tage 8 – 28: wöchentlich
|
||||||
|
# - Tage 29 – 365: monatlich
|
||||||
|
# - älter als 1 Jahr: werden gelöscht
|
||||||
|
|
||||||
set -e
|
set -eo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||||
|
BACKUP_DIR="$PROJECT_DIR/backups"
|
||||||
|
LOCK_FILE="/tmp/steuerkram-backup.lock"
|
||||||
|
|
||||||
|
# Verhindert mehrfachen gleichzeitigen Start (z.B. bei Verzögerung durch langen Backup-Lauf)
|
||||||
|
exec 9>"$LOCK_FILE"
|
||||||
|
if ! flock -n 9; then
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') WARN: Backup läuft bereits (Lock: $LOCK_FILE). Abbruch." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||||
BACKUP_DIR="./backups"
|
|
||||||
mkdir -p "$BACKUP_DIR"
|
mkdir -p "$BACKUP_DIR"
|
||||||
|
|
||||||
echo "Erstelle Backup $TIMESTAMP..."
|
echo "$(date '+%Y-%m-%d %H:%M:%S') Erstelle Backup $TIMESTAMP..."
|
||||||
|
|
||||||
# MariaDB Dump (aus dem Container)
|
# MariaDB Dump (aus dem Container)
|
||||||
docker compose exec -T db mariadb-dump \
|
docker compose -f "$PROJECT_DIR/docker-compose.yml" \
|
||||||
|
--project-directory "$PROJECT_DIR" \
|
||||||
|
exec -T db mariadb-dump \
|
||||||
--user=steuerkram \
|
--user=steuerkram \
|
||||||
--password=steuerkram \
|
--password=steuerkram \
|
||||||
--single-transaction \
|
--single-transaction \
|
||||||
|
|
@ -21,12 +40,67 @@ docker compose exec -T db mariadb-dump \
|
||||||
steuerkram > "$BACKUP_DIR/steuerkram_db_$TIMESTAMP.sql"
|
steuerkram > "$BACKUP_DIR/steuerkram_db_$TIMESTAMP.sql"
|
||||||
|
|
||||||
# Uploads sichern
|
# Uploads sichern
|
||||||
tar -czf "$BACKUP_DIR/steuerkram_uploads_$TIMESTAMP.tar.gz" ./uploads/
|
tar -czf "$BACKUP_DIR/steuerkram_uploads_$TIMESTAMP.tar.gz" \
|
||||||
|
-C "$PROJECT_DIR" uploads/
|
||||||
|
|
||||||
echo "Backup abgeschlossen:"
|
|
||||||
echo " DB: $BACKUP_DIR/steuerkram_db_$TIMESTAMP.sql"
|
echo " DB: $BACKUP_DIR/steuerkram_db_$TIMESTAMP.sql"
|
||||||
echo " Uploads: $BACKUP_DIR/steuerkram_uploads_$TIMESTAMP.tar.gz"
|
echo " Uploads: $BACKUP_DIR/steuerkram_uploads_$TIMESTAMP.tar.gz"
|
||||||
|
|
||||||
# Alte Backups löschen (älter als 90 Tage)
|
# --- Smarte Rotation ---
|
||||||
find "$BACKUP_DIR" -name "steuerkram_*" -mtime +90 -delete
|
echo ""
|
||||||
echo "Alte Backups bereinigt (>90 Tage)."
|
echo "Starte Rotation..."
|
||||||
|
|
||||||
|
NOW=$(date +%s)
|
||||||
|
declare -A keep_daily # YYYYMMDD → timestamp (letzte 7 Tage, täglich)
|
||||||
|
declare -A keep_weekly # Wochennr. → timestamp (Tage 8–28, wöchentlich)
|
||||||
|
declare -A keep_monthly # YYYYMM → timestamp (Tage 29–365, monatlich)
|
||||||
|
|
||||||
|
# Alle vorhandenen Timestamps ermitteln, älteste zuerst
|
||||||
|
# (neuere Einträge überschreiben Buckets → neuestes Backup pro Periode bleibt)
|
||||||
|
mapfile -t TIMESTAMPS < <(
|
||||||
|
for f in "$BACKUP_DIR"/steuerkram_db_????????_??????.sql; do
|
||||||
|
[ -f "$f" ] || continue
|
||||||
|
basename "$f" .sql | sed 's/steuerkram_db_//'
|
||||||
|
done | sort
|
||||||
|
)
|
||||||
|
|
||||||
|
for TS in "${TIMESTAMPS[@]}"; do
|
||||||
|
DATE_PART="${TS:0:8}" # YYYYMMDD
|
||||||
|
YEAR="${TS:0:4}"
|
||||||
|
MONTH="${TS:4:2}"
|
||||||
|
DAY="${TS:6:2}"
|
||||||
|
|
||||||
|
FILE_EPOCH=$(date -d "${YEAR}-${MONTH}-${DAY}" +%s)
|
||||||
|
AGE_DAYS=$(( (NOW - FILE_EPOCH) / 86400 ))
|
||||||
|
WEEK_BUCKET=$(( AGE_DAYS / 7 ))
|
||||||
|
|
||||||
|
if [ "$AGE_DAYS" -le 7 ]; then keep_daily["$DATE_PART"]="$TS"
|
||||||
|
elif [ "$AGE_DAYS" -le 28 ]; then keep_weekly["$WEEK_BUCKET"]="$TS"
|
||||||
|
elif [ "$AGE_DAYS" -le 365 ]; then keep_monthly["${YEAR}${MONTH}"]="$TS"
|
||||||
|
fi
|
||||||
|
# Älter als 365 Tage → kein Bucket → wird weiter unten gelöscht
|
||||||
|
done
|
||||||
|
|
||||||
|
# Keep-Set aus allen Buckets zusammenführen
|
||||||
|
declare -A KEEP
|
||||||
|
for TS in \
|
||||||
|
$([ ${#keep_daily[@]} -gt 0 ] && echo "${keep_daily[@]}") \
|
||||||
|
$([ ${#keep_weekly[@]} -gt 0 ] && echo "${keep_weekly[@]}") \
|
||||||
|
$([ ${#keep_monthly[@]} -gt 0 ] && echo "${keep_monthly[@]}") ; do
|
||||||
|
KEEP["$TS"]=1
|
||||||
|
done
|
||||||
|
|
||||||
|
# Backups löschen, die in keinem Bucket landen
|
||||||
|
DELETED=0
|
||||||
|
for TS in "${TIMESTAMPS[@]}"; do
|
||||||
|
if [ -z "${KEEP[$TS]+x}" ]; then
|
||||||
|
rm -f "$BACKUP_DIR/steuerkram_db_$TS.sql"
|
||||||
|
rm -f "$BACKUP_DIR/steuerkram_uploads_$TS.tar.gz"
|
||||||
|
echo " Gelöscht: $TS"
|
||||||
|
DELETED=$((DELETED + 1))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo " Behalten: ${#KEEP[@]} | täglich: ${#keep_daily[@]} | wöchentlich: ${#keep_weekly[@]} | monatlich: ${#keep_monthly[@]}"
|
||||||
|
echo " Gelöscht: $DELETED"
|
||||||
|
echo "$(date '+%Y-%m-%d %H:%M:%S') Backup & Rotation abgeschlossen."
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue