Files
darktable-sync/scripts/darktable_sync.sh
T
martin 6a6ce52cf9 Robuste Darktable-Synchronisation: sequenzieller Ablauf, Versions- und Concurrent-Schutz
- Race Condition behoben: Pre-Sync wird vollstaendig abgewartet bevor Darktable startet
- Post-Sync nach Schliessen von Darktable eingefuehrt (bisher fehlend)
- .env aus festem Pfad ~/.config/darktable-sync/.env geladen (nicht mehr relativ)
- Server-Erreichbarkeit per SSH statt ping (Firewall-sicher)
- Darktable-Versionscheck (Major.Minor) vor Download mit Abbruch bei Konflikt
- DB-Backup vor jedem Download (library.db.bak, data.db.bak)
- sync_pending-Marker bei Offline/Fehler, Hinweis beim naechsten Start
- darktable.active-Marker auf Server fuer Concurrent-Erkennung
- Lock-Dateien vom Sync ausgeschlossen
- systemd-Timer entfernt, Service bleibt als manueller Trigger
- Gemeinsame Hilfsfunktionen in darktable_common.sh extrahiert
- 20 BATS-Tests mit vollstaendigem Stub-System ohne GUI-Dialoge

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 19:41:26 +02:00

175 lines
5.4 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=darktable_common.sh
source "$SCRIPT_DIR/darktable_common.sh"
check_dependency rsync
check_dependency ssh openssh-client
check_dependency notify-send libnotify-bin
check_dependency darktable
load_config
validate_config
export DISPLAY="${DISPLAY:-:0}"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
}
count_synced_files() {
local log_file="$1" direction="$2" count=0
case "$direction" in
up) count=$(grep -cE '^>f|^cd' "$log_file" 2>/dev/null) || count=0 ;;
down) count=$(grep -cE '^<f|^cd' "$log_file" 2>/dev/null) || count=0 ;;
esac
echo "$count"
}
SCRIPT_NAME="$(basename "$0")"
LOCKFILE="/tmp/${SCRIPT_NAME}.lock"
if [ -e "$LOCKFILE" ]; then
echo "Script laeuft bereits oder Lockfile loeschen: $LOCKFILE"
exit 1
fi
touch "$LOCKFILE"
TMPFILES=("$LOCKFILE")
trap 'rm -f "${TMPFILES[@]}"' EXIT
SHOW_NOTIFY_START_STOP=false
if [[ "${1:-}" == "--with-notify-start-stop" ]]; then
SHOW_NOTIFY_START_STOP=true
fi
if [ -f "$CONFIG_DIR/sync_pending" ]; then
notify-send "Darktable Sync" "Ausstehender Sync wird jetzt ausgefuehrt..." -t 3000
fi
if ! server_reachable; then
log "Server nicht erreichbar Sync uebersprungen."
touch "$CONFIG_DIR/sync_pending"
exit 0
fi
if [ "$SHOW_NOTIFY_START_STOP" = true ]; then
notify-send "Darktable Sync" "Sync gestartet..." -t 3000
fi
ACTIVE=$(ssh -o ConnectTimeout=5 -o BatchMode=yes \
-p "$SERVER_SSH_PORT" "$SERVER_USER@$SERVER_IP" \
"cat '$SERVER_DB_DIR/darktable.active' 2>/dev/null || true")
if [ -n "$ACTIVE" ]; then
notify-send "Darktable Sync Warnung" \
"Darktable laueft moeglicherweise auf: $ACTIVE" -u normal -t 10000
fi
SERVER_VERSION=$(ssh -o ConnectTimeout=5 -o BatchMode=yes \
-p "$SERVER_SSH_PORT" "$SERVER_USER@$SERVER_IP" \
"cat '$SERVER_DB_DIR/darktable_version' 2>/dev/null || true")
LOCAL_VERSION=$(darktable --version 2>&1 | head -1)
if [ -n "$SERVER_VERSION" ]; then
LOCAL_MM=$(echo "$LOCAL_VERSION" | grep -oP '\d+\.\d+' | head -1 || true)
SERVER_MM=$(echo "$SERVER_VERSION" | grep -oP '\d+\.\d+' | head -1 || true)
if [ -n "$SERVER_MM" ] && [ "$LOCAL_MM" != "$SERVER_MM" ]; then
log "WARNUNG: Darktable-Versionen unterschiedlich!"
log " Lokal: $LOCAL_VERSION"
log " Server: $SERVER_VERSION"
log " Bitte beide Rechner auf gleichen Stand bringen."
notify-send "Darktable Sync Versionskonflikt" \
"Lokal: $LOCAL_MM Server: $SERVER_MM\nBitte angleichen!" \
-u critical
touch "$CONFIG_DIR/sync_pending"
exit 1
fi
fi
log "Datenbank-Backup erstellen..."
cp "$LOCAL_DARKTABLE_DB_DIR/library.db" "$LOCAL_DARKTABLE_DB_DIR/library.db.bak"
cp "$LOCAL_DARKTABLE_DB_DIR/data.db" "$LOCAL_DARKTABLE_DB_DIR/data.db.bak"
SYNC_LOG=$(mktemp)
TMPFILES+=("$SYNC_LOG")
log "Datenbank hochladen..."
UPLOAD_LOG_DB=$(mktemp)
TMPFILES+=("$UPLOAD_LOG_DB")
if ! rsync -uavh --itemize-changes \
--exclude '*.lock' \
--exclude 'darktable_version' \
-e "ssh -p $SERVER_SSH_PORT" \
"$LOCAL_DARKTABLE_DB_DIR/" "$SERVER_USER@$SERVER_IP:$SERVER_DB_DIR/" \
2>&1 | tee -a "$SYNC_LOG" "$UPLOAD_LOG_DB"; then
log "Fehler beim Hochladen der Datenbank."
touch "$CONFIG_DIR/sync_pending"
exit 1
fi
SENT_DB=$(count_synced_files "$UPLOAD_LOG_DB" "up")
log "Fotos hochladen..."
UPLOAD_LOG_PHOTOS=$(mktemp)
TMPFILES+=("$UPLOAD_LOG_PHOTOS")
if ! rsync -uavh --itemize-changes \
--exclude '*.lock' \
-e "ssh -p $SERVER_SSH_PORT" \
"$LOCAL_PHOTO_DIR/" "$SERVER_USER@$SERVER_IP:$SERVER_PHOTO_DIR/" \
2>&1 | tee -a "$SYNC_LOG" "$UPLOAD_LOG_PHOTOS"; then
log "Fehler beim Hochladen der Fotos."
touch "$CONFIG_DIR/sync_pending"
exit 1
fi
SENT_PHOTOS=$(count_synced_files "$UPLOAD_LOG_PHOTOS" "up")
log "Datenbank herunterladen..."
DOWNLOAD_LOG_DB=$(mktemp)
TMPFILES+=("$DOWNLOAD_LOG_DB")
if ! rsync -uavh --itemize-changes \
--exclude '*.lock' \
-e "ssh -p $SERVER_SSH_PORT" \
"$SERVER_USER@$SERVER_IP:$SERVER_DB_DIR/" "$LOCAL_DARKTABLE_DB_DIR/" \
2>&1 | tee -a "$SYNC_LOG" "$DOWNLOAD_LOG_DB"; then
log "Fehler beim Herunterladen der Datenbank."
touch "$CONFIG_DIR/sync_pending"
exit 1
fi
RECEIVED_DB=$(count_synced_files "$DOWNLOAD_LOG_DB" "down")
log "Fotos herunterladen..."
DOWNLOAD_LOG_PHOTOS=$(mktemp)
TMPFILES+=("$DOWNLOAD_LOG_PHOTOS")
if ! rsync -uavh --itemize-changes \
--exclude '*.lock' \
-e "ssh -p $SERVER_SSH_PORT" \
"$SERVER_USER@$SERVER_IP:$SERVER_PHOTO_DIR/" "$LOCAL_PHOTO_DIR/" \
2>&1 | tee -a "$SYNC_LOG" "$DOWNLOAD_LOG_PHOTOS"; then
log "Fehler beim Herunterladen der Fotos."
touch "$CONFIG_DIR/sync_pending"
exit 1
fi
RECEIVED_PHOTOS=$(count_synced_files "$DOWNLOAD_LOG_PHOTOS" "down")
echo "$LOCAL_VERSION" > "$LOCAL_DARKTABLE_DB_DIR/darktable_version"
rm -f "$CONFIG_DIR/sync_pending"
TOTAL_SENT=$((SENT_DB + SENT_PHOTOS))
TOTAL_RECEIVED=$((RECEIVED_DB + RECEIVED_PHOTOS))
if [ "$TOTAL_SENT" -gt 0 ] || [ "$TOTAL_RECEIVED" -gt 0 ]; then
log "Hochgeladen: $TOTAL_SENT Dateien"
log "Heruntergeladen: $TOTAL_RECEIVED Dateien"
notify-send "Darktable Sync" \
"$TOTAL_SENT hochgeladen | ↓ $TOTAL_RECEIVED heruntergeladen" -t 10000
else
log "Keine Aenderungen."
fi
if [ "$SHOW_NOTIFY_START_STOP" = true ]; then
notify-send "Darktable Sync" "Sync abgeschlossen." -t 3000
fi