.
This commit is contained in:
206
unRAID Userscript/README.MD
Normal file
206
unRAID Userscript/README.MD
Normal file
@@ -0,0 +1,206 @@
|
||||
# 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
|
||||
```
|
||||
Reference in New Issue
Block a user