3.9 KiB
Music Sync Script (Unraid)
Zweck
Synchronisiert neue Musikdateien aus incoming in zwei Zielordner.
Dateien werden nur verarbeitet, wenn sie vollständig geschrieben sind.
Ablauf
incoming → ready → DEST1 + DEST2 → delete
Warum incoming → ready?
Das Script verwendet zwei Verzeichnisse, um einen sauberen und sicheren Verarbeitungszustand zu gewährleisten.
Problem ohne Trennung
Wenn direkt aus incoming synchronisiert wird:
- Dateien können noch geschrieben werden (z. B. durch Picard)
rsynckopiert ggf. unvollständige Dateien- bei mehreren Durchläufen entstehen Inkonsistenzen zwischen den Zielen
Lösung: Staging mit ready
Der Ablauf ist bewusst zweistufig:
incoming (unsicher) → ready (stabil) → Sync
incoming
- hier schreibt Picard
- Dateien können noch im Zugriff sein
- kein Sync von hier
ready
- Dateien werden erst verschoben, wenn sie alt genug sind
mvinnerhalb desselben Filesystems ist atomar- Datei ist danach garantiert vollständig
👉 Ergebnis:
Das Script arbeitet nur mit fertigen, stabilen Dateien.
Wichtiger Hinweis zu "atomar"
Ein mv ist nur dann atomar, wenn sich Quelle und Ziel im selben Filesystem befinden.
In diesem Setup:
INCOMING="/mnt/user/Cache/Picard/incoming"
READY="/mnt/user/Cache/Picard/ready"
liegen beide Pfade im selben Share → gleicher Storage → atomarer Move.
Wichtig:
- Es ist egal, wo Picard läuft (Docker, anderer Host, etc.)
- Entscheidend ist nur, wohin geschrieben wird
Nicht atomar wäre z. B.:
/mnt/user/... → /mnt/diskX/...
Dann würde mv intern kopieren + löschen.
Lockfile
/mnt/user/Cache/Picard/sync.lock
Zweck
- verhindert parallele Ausführung
- schützt vor doppelten Operationen
Problemfall
Wenn das Script abbricht, bleibt das Lockfile bestehen und blockiert weitere Runs.
Lösung
rm /mnt/user/Cache/Picard/sync.lock
Nur ausführen, wenn sicher kein Script mehr läuft.
CHOWN (Dateirechte / CIFS Problem)
Nach dem Kopieren werden Dateien und Ordner explizit gesetzt auf:
CHOWN_USER="thorsten"
CHOWN_GROUP="users"
Warum ist das nötig?
Unraid + CIFS/Samba verhält sich so:
- Dateien werden oft als
rootodernobodyangelegt - Netzwerkzugriff über CIFS hat dann keine Löschrechte
- selbst wenn Lesen funktioniert
👉 Typisches Symptom: Datei kann geöffnet, aber nicht gelöscht werden
Lösung im Script
Nach erfolgreichem Sync:
- wird jede Datei gechowned
- zugehörige Ordner werden ebenfalls angepasst
- Ordner aber nur einmal pro Lauf (Performance)
👉 Ergebnis:
- Dateien gehören deinem User
- CIFS Zugriff funktioniert korrekt
- kein manuelles
chown -Rmehr nötig
Eigenschaften
- verarbeitet nur Dateien älter als 1 Minute
- atomarer Move (incoming → ready)
- Sync zu zwei Zielen per rsync
- Löschen nur bei Erfolg beider Syncs
- fehlgeschlagene Dateien bleiben erhalten
- Lockfile verhindert parallele Ausführung
- Dry-Run Modus vorhanden
- Logging + Konsolenausgabe
- Pfade tolerant gegenüber trailing
/ - Zielpfade müssen existieren (sonst Abbruch)
- Ownership wird gesetzt (
chown) - Ordner werden nur einmal pro Lauf angepasst
Konfiguration
INCOMING="/mnt/user/Cache/Picard/incoming"
READY="/mnt/user/Cache/Picard/ready"
DEST1="/mnt/user/Cache/Syncthing/..."
DEST2="/mnt/user/Media/Musik/..."
LOG="/mnt/user/Cache/Picard/sync.log"
LOCKFILE="/mnt/user/Cache/Picard/sync.lock"
DRY_RUN=false
CHOWN_USER="thorsten"
CHOWN_GROUP="users"
Dry Run
DRY_RUN=true
- keine Änderungen am Dateisystem
- rsync läuft mit --dry-run
- Aktionen werden geloggt
Cron Beispiel
0 */6 * * *
Hinweise
- Script beendet sich sofort, wenn keine Dateien vorhanden sind
ready/wird nur bei Bedarf erstellt und kann wieder verschwinden- Rechteproblem bei CIFS wird durch chown gelöst
Debug
cat /mnt/user/Cache/Picard/sync.log
ls /mnt/user/Cache/Picard