From c0aafa2d34d9c246038f333bc3e2518aebd6ba57 Mon Sep 17 00:00:00 2001 From: alf Date: Tue, 29 Sep 2026 12:18:58 +0000 Subject: [PATCH] =?UTF-8?q?kosolidierencloud.sh=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kosolidierencloud.sh | 172 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 kosolidierencloud.sh diff --git a/kosolidierencloud.sh b/kosolidierencloud.sh new file mode 100644 index 0000000..2faf81d --- /dev/null +++ b/kosolidierencloud.sh @@ -0,0 +1,172 @@ +#!/usr/bin/env bash +# +# magenta-konsolidierung.sh +# +# Cloud-Konsolidierung ohne Remote-Skript: laedt nur die noetigen Ordner aus +# der Magentacloud (rclone) herunter, konsolidiert sie lokal und schiebt das +# Ergebnis zurueck. Quellordner werden auf dem Remote erst geloescht, wenn +# das Ergebnis dort liegt. +# +# Ablauf pro Lauf: +# 1. Tagesordner JJJJ-MM-TT-HH des zuletzt abgeschlossenen Monats +# herunterladen -> zu Monatsordner JJJJ-MM konsolidieren -> hochladen +# -> Tagesordner auf dem Remote loeschen. +# 2. Falls Monatsordner aelter als RETAIN_MONTHS sind: diese ebenfalls +# herunterladen -> zu Jahresordner JJJJ konsolidieren -> hochladen +# -> Monatsordner auf dem Remote loeschen. +# +# Nutzung: +# ./magenta-konsolidierung.sh [-n] +# -n = Dry-Run (zeigt nur, was passieren wuerde) +# +set -euo pipefail + +REMOTE="magenta:Technik/DPV_Archiv" # rclone-remote:Pfad zum Archiv +WORK="/tmp/magenta-konsolidierung" # lokales Arbeitsverzeichnis +RETAIN_MONTHS=3 # Monatsordner juenger als x Monate bleiben Monatsordner +DRY_RUN=0 +LOG_FILE="" + +log() { + local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*" + echo "$msg" + if [ -n "$LOG_FILE" ]; then echo "$msg" >> "$LOG_FILE"; fi + return 0 +} + +usage() { echo "Usage: $0 [-n]" >&2; exit 1; } +while getopts "n" opt; do + case "$opt" in + n) DRY_RUN=1 ;; + *) usage ;; + esac +done + +rclone_do() { + if [ "$DRY_RUN" -eq 1 ]; then + log "[Dry-Run] rclone $*" + else + log "rclone $*" + rclone "$@" + fi +} + +# ---- Hilfsfunktionen ------------------------------------------------------- + +# zuletzt abgeschlossener Monat als JJJJ-MM +last_closed_month() { + date -d "$(date +%Y-%m-01) -1 day" +%Y-%m +} + +# Monatsdifferenz (a - b) zwischen zwei Werten JJJJ-MM, negativ wenn a frueher +month_diff() { + local a="$1" b="$2" + local ay am by bm + ay=${a%%-*}; am=${a##*-} + by=${b%%-*}; bm=${b##*-} + echo $(( (10#$ay * 12 + 10#$am) - (10#$by * 12 + 10#$bm) )) +} + +# lokale Konsolidierung: alle Ordner in "$1" (aufsteigend sortiert, aeltester +# zuerst) zu Ordner "$2" zusammenfuehren; spaetere Laeufe ueberschreiben fruehere, +# die aktuellste Version gewinnt also. +merge_local() { + local srcdir="$1" dest="$2" + local first=1 d + mkdir -p "$dest" + for d in "$srcdir"/*; do + [ -d "$d" ] || continue + if [ "$first" -eq 1 ]; then + if [ "$DRY_RUN" -eq 1 ]; then + log "[Dry-Run] mv $d -> $dest (Grundordner)" + else + mv "$d" "$dest" + fi + first=0 + else + if [ "$DRY_RUN" -eq 1 ]; then + log "[Dry-Run] merge $d -> $dest" + else + cp -a "$d/." "$dest/" + fi + fi + done +} + +# ---- Vorbereitung ---------------------------------------------------------- + +CLOSED="$(last_closed_month)" +TODAY_MONTH="$(date +%Y-%m)" + +if [ "$DRY_RUN" -ne 1 ]; then + rm -rf "$WORK" + mkdir -p "$WORK" +fi + +# Remote-Bestand einmal abfragen (nur Verzeichnisnamen) +mapfile -t REMOTE_DIRS < <(rclone lsf "${REMOTE%/}/" --dirs-only 2>/dev/null | sed 's:/$::') + +# ---- Stufe 1: Tagesordner des Vormonats -> Monatsordner -------------------- + +MONTH_SOURCES=() +for d in "${REMOTE_DIRS[@]}"; do + [[ "$d" =~ ^${CLOSED}-[0-9]{2}-[0-9]{2}$ ]] || continue + MONTH_SOURCES+=("$d") +done + +if [ ${#MONTH_SOURCES[@]} -gt 0 ]; then + log "Stufe 1: ${#MONTH_SOURCES[@]} Tagesordner fuer Monat $CLOSED konsolidieren" + for d in "${MONTH_SOURCES[@]}"; do + rclone_do copy "${REMOTE%/}/$d" "$WORK/tage/$d" + done + merge_local "$WORK/tage" "$WORK/out/$CLOSED" + # erst Ergebnis hochladen, dann Quellordner auf dem Remote entfernen + rclone_do copy "$WORK/out/$CLOSED" "${REMOTE%/}/$CLOSED" + for d in "${MONTH_SOURCES[@]}"; do + rclone_do purge "${REMOTE%/}/$d" + done +else + log "Stufe 1: keine Tagesordner fuer $CLOSED vorhanden (nichts zu tun)" +fi + +# ---- Stufe 2: alte Monatsordner -> Jahresordner ---------------------------- + +YEAR_FOLDERS=() +for d in "${REMOTE_DIRS[@]}"; do + [[ "$d" =~ ^[0-9]{4}-[0-9]{2}$ ]] || continue + diff=$(month_diff "$d" "$TODAY_MONTH") + if [ "$diff" -ge 0 ] || [ $(( -diff )) -lt "$RETAIN_MONTHS" ]; then + continue # juenger als RETAIN_MONTHS: als Monatsordner stehen lassen + fi + YEAR_FOLDERS+=("$d") +done + +if [ ${#YEAR_FOLDERS[@]} -gt 0 ]; then + log "Stufe 2: ${#YEAR_FOLDERS[@]} Monatsordner in Jahresordner konsolidieren" + # aufsteigend sortiert, damit neuere Monatsordner aeltere ueberschreiben + mapfile -t YEAR_FOLDERS < <(printf '%s\n' "${YEAR_FOLDERS[@]}" | sort) + current_year="" + for m in "${YEAR_FOLDERS[@]}"; do + yr="${m:0:4}" + if [ "$yr" != "$current_year" ]; then + current_year="$yr" + mkdir -p "$WORK/monate/$yr" + fi + rclone_do copy "${REMOTE%/}/$m" "$WORK/monate/$yr/$m" + done + # je Jahr konsolidieren, hochladen, dann Quellen auf dem Remote loeschen + for yr in "$WORK/monate"/*; do + [ -d "$yr" ] || continue + y="$(basename "$yr")" + merge_local "$yr" "$WORK/out/$y" + rclone_do copy "$WORK/out/$y" "${REMOTE%/}/$y" + done + for m in "${YEAR_FOLDERS[@]}"; do + rclone_do purge "${REMOTE%/}/$m" + done +else + log "Stufe 2: keine Monatsordner aelter als $RETAIN_MONTHS Monate (nichts zu tun)" +fi + +log "Fertig." +[ "$DRY_RUN" -eq 1 ] && log "(Dry-Run: nichts wurde veraendert.)" \ No newline at end of file