From 05ab655116cadd9964b8f074f2c4cf2d63f72dd0 Mon Sep 17 00:00:00 2001 From: Hitonabi Date: Fri, 28 Aug 2026 09:35:48 +0200 Subject: [PATCH] fix: ein fehlendes Laufwerk darf Rippy nicht am Starten hindern MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit WAS: Die `devices:`-Eintraege fliegen aus docker-compose.yml. Was dieser Host wirklich hat, ermittelt deploy/geraete-override.sh und schreibt es in docker-compose.override.yml — die zieht Compose von allein dazu, der Befehl bleibt `docker compose up -d`. WARUM (Vorfall heute, 28.08.2026): Das USB-Laufwerk haengt nicht mehr an der VM. Ein ganz normaler Deploy legte daraufhin api, worker UND ui still: Error response from daemon: error gathering device information while adding custom device "/dev/sr0": no such file or directory Ein `devices:`-Eintrag ist eine STARTBEDINGUNG — und keiner der drei Container braucht zum STARTEN ein Laufwerk. Rippy war unten, und die Meldung stand mitten im Build-Rauschen (dieselbe Klasse wie das geschluckte `|| echo` beim .env-Kopieren am 26.07.). DER WIDERSPRUCH WAR AELTER ALS DER VORFALL: install.sh sagt bei fehlendem Laufwerk ausdruecklich "die Installation laeuft trotzdem durch; diese Maschine dient dann als reine KOMPRIMIER-Maschine" — die Compose-Datei sah das anders. Eine Maschine ohne Laufwerk ist ein VORGESEHENER Betriebsfall: der Windows-Worker und der GPU-Encoder sind genau das. Das Skript uebernimmt die Erkennung aus install.sh unveraendert: sr- und sg-Knoten ueber die SCSI-Adresse in /sys abgeglichen, nicht geraten. Und es schreibt die Override AUCH dann, wenn kein Laufwerk da ist — sonst bliebe eine alte Datei mit /dev/sr0 liegen und der Fehler waere derselbe, nur schwerer zu finden, weil sie gitignored ist und in keinem Diff auftaucht. deploy.sh ruft es vor dem Start auf. Co-Authored-By: Claude Opus 5 --- deploy.sh | 12 ++++ deploy/geraete-override.sh | 112 +++++++++++++++++++++++++++++++++++++ docker-compose.yml | 36 ++++++++---- 3 files changed, 148 insertions(+), 12 deletions(-) create mode 100644 deploy/geraete-override.sh diff --git a/deploy.sh b/deploy.sh index 5dac5c2..17e9738 100644 --- a/deploy.sh +++ b/deploy.sh @@ -95,6 +95,18 @@ fi sed -i '/^RIPPY_VERSION=/d' .env echo "RIPPY_VERSION=$(git rev-parse --short HEAD)" >> .env +# Geraete dieses Hosts ermitteln, BEVOR gestartet wird. +# Ohne diesen Schritt haengt der Start an einem `devices:`-Eintrag, den es +# vielleicht nicht mehr gibt — am 28.08.2026 legte genau das die ganze +# Installation stillt, weil das USB-Laufwerk abgezogen war (Herleitung im Kopf +# von docker-compose.yml). Das Skript schreibt die Override immer neu, auch +# wenn kein Laufwerk da ist. +if [ -x ./deploy/geraete-override.sh ]; then + ./deploy/geraete-override.sh . +else + echo "WARNUNG: deploy/geraete-override.sh fehlt — starte ohne Geraete-Erkennung." +fi + docker compose -p rippy up -d --build $DIENST docker compose -p rippy ps --format 'table {{.Name}}\t{{.Status}}' REMOTE diff --git a/deploy/geraete-override.sh b/deploy/geraete-override.sh new file mode 100644 index 0000000..b45300d --- /dev/null +++ b/deploy/geraete-override.sh @@ -0,0 +1,112 @@ +#!/usr/bin/env bash +# +# Erzeugt docker-compose.override.yml mit den optischen Laufwerken DIESES Hosts. +# +# ## Warum es das gibt (Vorfall 28.08.2026) +# +# In docker-compose.yml stand: +# +# devices: +# - ${OPTICAL_SR:-/dev/sr0}:/dev/sr0 +# +# Das ist eine STARTBEDINGUNG. Fehlt das Laufwerk, startet der Container nicht: +# +# Error response from daemon: error gathering device information while +# adding custom device "/dev/sr0": no such file or directory +# +# Genau das ist passiert, als das USB-Laufwerk von der VM abgezogen wurde: Ein +# ganz normaler Deploy legte api, worker UND ui still — obwohl keiner der drei +# ein Laufwerk zum Starten braucht. Rippy war unten, und die Meldung stand +# mitten im Build-Rauschen. +# +# Der Widerspruch war schon vorher da: `install.sh` sagt bei fehlendem Laufwerk +# ausdrücklich „die Installation läuft trotzdem durch; diese Maschine dient dann +# als reine KOMPRIMIER-Maschine" — die Compose-Datei sah das anders. Eine +# Maschine ohne Laufwerk ist ein vorgesehener Betriebsfall (der Windows-Worker +# und der GPU-Encoder sind genau das). +# +# Seither steht in docker-compose.yml KEIN devices-Block mehr. Was dieser Host +# wirklich hat, landet in docker-compose.override.yml — die zieht Compose von +# allein dazu (`docker compose up` braucht keinen extra Schalter), und sie ist +# gitignored, weil die Geräteknoten je Rechner anders heißen. +# +# Aufruf: ./deploy/geraete-override.sh [zielverzeichnis] +# (ohne Argument: das aktuelle Verzeichnis) +# +set -u + +ZIEL="${1:-.}" +DATEI="$ZIEL/docker-compose.override.yml" + +# MakeMKV spricht Laufwerke über die SCSI-Generic-Schicht an und braucht deshalb +# ZWEI Knoten: /dev/srN und den passenden /dev/sgM. Welche sg-Nummer dazugehört, +# ist je Host anders — sie wird über die SCSI-Adresse ermittelt statt geraten. +# Beide Knoten zeigen in /sys auf dasselbe Geräteverzeichnis (z. B. 3:0:0:0). +# (Dieselbe Herleitung wie in install.sh, Prüfung 2/5.) +SR="" +SG="" +LAUFWERK="" +for srpfad in /sys/block/sr*; do + [ -e "$srpfad" ] || continue + srname=$(basename "$srpfad") + adresse=$(basename "$(readlink -f "$srpfad/device" 2>/dev/null)" 2>/dev/null) + [ -n "$adresse" ] || continue + for sgpfad in /sys/class/scsi_generic/sg*; do + [ -e "$sgpfad" ] || continue + if [ "$(basename "$(readlink -f "$sgpfad/device" 2>/dev/null)" 2>/dev/null)" = "$adresse" ]; then + SR="/dev/$srname" + SG="/dev/$(basename "$sgpfad")" + LAUFWERK="$(cat "$srpfad/device/vendor" 2>/dev/null) $(cat "$srpfad/device/model" 2>/dev/null)" + break 2 + fi + done +done + +kopf() { + cat < "$DATEI" + echo "Kein optisches Laufwerk gefunden — $DATEI ohne Geräte geschrieben." + echo "Rippy startet und kann komprimieren; Rippen geht erst mit Laufwerk." + exit 0 +fi + +{ + kopf + echo "#" + echo "# Gefunden: $(echo "$LAUFWERK" | tr -s ' ')" + echo "# $SR + $SG (über die SCSI-Adresse abgeglichen, nicht geraten)" + cat < "$DATEI" + +echo "Laufwerk gefunden: $(echo "$LAUFWERK" | tr -s ' ')" +echo " $SR + $SG -> $DATEI" diff --git a/docker-compose.yml b/docker-compose.yml index 3f5d0d8..a868228 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,24 @@ # Geräte-Zugriff (22.07./23.07.-Lehre): Optische Laufwerke MÜSSEN als devices: # eingebunden werden. Bind-Mounts unter volumes: geben dem Container zwar den # Geräteknoten, aber KEINE Berechtigung im Device-Cgroup → jedes open() scheitert -# mit EPERM. Voraussetzung: Die VM sieht das Laufwerk (USB-Passthrough auf pve). +# mit EPERM. +# +# ⚠️ ABER NICHT HIER (Vorfall 28.08.2026): Ein `devices:`-Eintrag ist eine +# STARTBEDINGUNG. Als das USB-Laufwerk von der VM abgezogen wurde, legte ein +# ganz normaler Deploy api, worker UND ui still — obwohl keiner der drei zum +# Starten ein Laufwerk braucht: +# +# Error response from daemon: error gathering device information while +# adding custom device "/dev/sr0": no such file or directory +# +# Der Widerspruch war älter: install.sh sagt bei fehlendem Laufwerk +# ausdrücklich „läuft trotzdem durch, dann ist das eine reine +# KOMPRIMIER-Maschine" — diese Datei sah das anders. +# +# Deshalb stehen die Geräte jetzt in docker-compose.override.yml, erzeugt von +# `deploy/geraete-override.sh`. Compose zieht die Override von allein dazu; +# `docker compose up -d` bleibt derselbe Befehl. Nach jedem An- oder Abstecken +# eines Laufwerks das Skript erneut aufrufen. services: api: @@ -54,8 +71,7 @@ services: - temp:/app/temp # MakeMKV-Datenverzeichnis (dasselbe wie im Worker, siehe dort). - ${MAKEMKV_DATA_HOST:-/srv/rippy/makemkv}:/app/makemkv-data - devices: - - ${OPTICAL_SR:-/dev/sr0}:/dev/sr0 + # devices: siehe Kopf — kommen aus docker-compose.override.yml networks: - rippy-net depends_on: @@ -118,15 +134,11 @@ services: # Ohne diesen Mount löschte JEDER `up -d --build` beides; die # Fehlermeldung schickte den Nutzer zu einer Datei, die es nicht mehr gab. - ${MAKEMKV_DATA_HOST:-/srv/rippy/makemkv}:/root/.MakeMKV - devices: - # Host-Geräteknoten via .env (OPTICAL_SR/OPTICAL_SG) — je Rechner ANDERS! - # MakeMKV spricht Laufwerke über die SCSI-Generic-Schicht an; ohne den - # passenden sg-Knoten findet es „keine usable optical drives". Den sg-Knoten - # des Laufwerks auf DIESEM Host ermitteln (lsscsi -g) und in die .env eintragen. - # Achtung: nach USB-Reconnect zur Laufzeit kann die sg-Nummer wandern → - # Container neu starten. Defaults (sr0/sg1) passen für den Ursprungs-Host. - - ${OPTICAL_SR:-/dev/sr0}:/dev/sr0 - - ${OPTICAL_SG:-/dev/sg1}:/dev/sg1 + # devices: siehe Kopf dieser Datei — die optischen Knoten dieses Hosts + # stehen in docker-compose.override.yml (deploy/geraete-override.sh). + # MakeMKV braucht BEIDE: /dev/srN und den passenden /dev/sgM; welche + # sg-Nummer dazugehoert, ist je Host anders und wird dort ueber die + # SCSI-Adresse abgeglichen statt geraten. networks: - rippy-net depends_on: