diff --git a/macos/backup-bfds-storage-offsite/backup-bfds-storage-offsite.sh b/macos/backup-bfds-storage-offsite/backup-bfds-storage-offsite.sh index d0dd1ce..40e3446 100755 --- a/macos/backup-bfds-storage-offsite/backup-bfds-storage-offsite.sh +++ b/macos/backup-bfds-storage-offsite/backup-bfds-storage-offsite.sh @@ -37,6 +37,12 @@ DEVICE="${DEVICE:-}" MOUNTED_BY_US=0 +# Run-Protokoll: pro Lauf eine JSON-Zeile, aus der das Dashboard den letzten +# durchgehenden Run (alle Freigaben fehlerfrei) abliest. +RUN_LOG_FILE="${RUN_LOG_FILE:-}" +RUN_START="$(date -u '+%Y-%m-%dT%H:%M:%SZ')" +SHARE_RESULTS="" + log() { printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" } @@ -54,6 +60,35 @@ unmount_volume() { MOUNTED_BY_US=0 } +# Ergebnis einer Freigabe merken: ok, source_missing, unreadable oder rsync_ +record_share() { + SHARE_RESULTS="${SHARE_RESULTS:+$SHARE_RESULTS,}\"$1\":\"$2\"" +} + +# Haengt am Ende jedes Laufs (auch bei Fehler oder Abbruch) eine JSON-Zeile an +# ~/Library/Logs/bfds-offsite-backup.jsonl an. "complete" ist nur wahr, wenn das +# Script mit 0 endete und jede Freigabe "ok" war. +write_run_record() { + local rc="$1" end ok total="${#SHARES[@]}" complete=false home + end="$(date -u '+%Y-%m-%dT%H:%M:%SZ')" + ok="$(printf '%s' "$SHARE_RESULTS" | grep -o ':"ok"' | wc -l | tr -d ' ')" + [ "$rc" -eq 0 ] && [ "$ok" -eq "$total" ] && complete=true + if [ -z "$RUN_LOG_FILE" ]; then + home="$HOME" + if [ -n "${SUDO_USER:-}" ]; then + home="$(dscl . -read "/Users/$SUDO_USER" NFSHomeDirectory 2>/dev/null | awk '{print $2}')" + [ -n "$home" ] || home="$HOME" + fi + RUN_LOG_FILE="$home/Library/Logs/bfds-offsite-backup.jsonl" + fi + mkdir -p "$(dirname "$RUN_LOG_FILE")" 2>/dev/null + printf '{"start":"%s","end":"%s","exit_code":%s,"complete":%s,"shares":{%s}}\n' \ + "$RUN_START" "$end" "$rc" "$complete" "$SHARE_RESULTS" >> "$RUN_LOG_FILE" \ + || { log "WARNUNG: Run-Protokoll konnte nicht geschrieben werden: $RUN_LOG_FILE"; return 0; } + # Unter sudo gehoert die Datei sonst root + if [ -n "${SUDO_USER:-}" ]; then chown "$SUDO_USER" "$RUN_LOG_FILE" 2>/dev/null || true; fi +} + # Die Disk-Nummer wechselt (disk4, disk6, ...). Gesucht wird daher die # Partition 1 auf externen, physischen Platten, die >= MIN_SIZE_GB gross sind # und nicht von macOS eingebunden werden koennen (Typ "Microsoft Basic Data", @@ -81,7 +116,7 @@ find_offsite_partition() { echo "${found[0]}" } -trap 'unmount_volume' EXIT +trap 'rc=$?; unmount_volume; write_run_record "$rc"' EXIT trap 'log "Abgebrochen"; exit 130' INT TERM # ************************************************** @@ -172,6 +207,7 @@ run_rsync() { if [ ! -d "$source" ]; then log "WARNUNG: Quelle nicht gefunden, bitte SMB-Freigabe oeffnen: smb://$SOURCE_HOST/$share" EXIT_CODE=1 + record_share "$share" source_missing return fi @@ -179,6 +215,7 @@ run_rsync() { if ! run_with_timeout "$PROBE_TIMEOUT" probe_source "$source"; then log "WARNUNG: $source nicht lesbar (haengt oder Fehler), ueberspringe $share. Freigabe im Finder trennen und neu verbinden." EXIT_CODE=1 + record_share "$share" unreadable return fi @@ -202,6 +239,9 @@ run_rsync() { if [ "$rc" -ne 0 ]; then log "WARNUNG: rsync fuer $share endete mit Code $rc" EXIT_CODE=1 + record_share "$share" "rsync_$rc" + else + record_share "$share" ok fi }