Files
Musicbrainz-Picard/unRAID Userscript
2026-04-02 14:25:30 +02:00
..
.
2026-04-02 14:25:30 +02:00
.
2026-03-25 18:56:41 +01:00

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)
  • rsync kopiert 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
  • mv innerhalb 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 root oder nobody angelegt
  • 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 -R mehr 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