#!/usr/bin/env bash # Gemeinsame Abbau-Funktion fuer Benchmark-Testserver. # # WARUM ES DIESE DATEI GIBT: die Benchmark-Skripte benutzten # `pgrep -x llama-server` zum Aufraeumen. Das trifft aber AUCH die Produktion — # PropellerAs Backend (:8290) und gemma-de (:8270) sind ebenfalls # llama-server-Prozesse. Am 16.08. hat run_extra.sh damit den kompletten # Primaerstack abgeraeumt, waehrend der Chat lief. # # Unterscheidungsmerkmal sind die bekannten PRODUKTIONS-UNITS und -PORTS — # NICHT mehr die Frage, ob ein Prozess in /system.slice/ liegt. # # FALLE 1 (17.08., vier Stunden Leerlauf): das Muster war erst `*.service*`. # Der Pfad einer Benutzer-Shell lautet # 0::/user.slice/user-1001.slice/user@1001.service/tmux-spawn-...scope # Da steht `user@1001.service` mittendrin, also galt der Testserver als # geschuetzte Produktion und ueberlebte. Er hielt 33 GB VRAM fest. # # FALLE 2 (20.08., aus derselben Wurzel): daraufhin wurde auf den Pfad-Praefix # /system.slice/ umgestellt — richtig, solange Testlaeufe aus einer Shell # kommen. In derselben Nacht wanderten die Messlaeufe in eine System-Unit # (`systemd-run --unit=nachtmessung`), damit sie das Sitzungsende ueberleben. # Damit lag der Testserver plotzlich SELBST unter # 0::/system.slice/nachtmessung.service # und die Schutzregel bewahrte genau den Prozess, den sie abraeumen sollte: # 31,7 GB VRAM blieben belegt, der naechste Messteil haette keinen Speicher # mehr gefunden. # # Lehre: "wo laeuft der Prozess" ist ein Indiz, das sich mit dem Startverfahren # aendert. "Welche Unit / welcher Port" ist eine Eigenschaft der Produktion # selbst. Deshalb wird jetzt eine ausdrueckliche Liste gefuehrt — wer einen # neuen Produktivdienst aufsetzt, traegt ihn hier ein. # # Pruefen laesst sich die Lage jederzeit mit # for p in $(pgrep -x llama-server); do head -1 /proc/$p/cgroup; done PRODUKTIONSPORTS="${PRODUKTIONSPORTS:-8290 8270 8275 8210}" PRODUKTIONSUNITS="${PRODUKTIONSUNITS:-propellerA gemma-de reranker ollama chatterbox}" # Gibt die PIDs aus, die gefahrlos beendet werden duerfen. testserver_pids() { local p cg cmd port einheit geschuetzt for p in $(pgrep -x llama-server 2>/dev/null); do cg=$(head -1 "/proc/$p/cgroup" 2>/dev/null) || continue cmd=$(tr '\0' ' ' < "/proc/$p/cmdline" 2>/dev/null) geschuetzt=0 for einheit in $PRODUKTIONSUNITS; do case "$cg" in *"/$einheit.service"*) geschuetzt=1 ;; esac done [ "$geschuetzt" = 1 ] && continue for port in $PRODUKTIONSPORTS; do case "$cmd" in *"--port $port"*) geschuetzt=1 ;; esac done [ "$geschuetzt" = 1 ] && continue echo "$p" done } # Beendet ausschliesslich Testserver. Produktion bleibt unangetastet. # # Meldet, WAS beendet wurde und was ueberlebt hat. Die stille Variante hat den # 17.08. verschluckt: der Abbau fand nichts, sagte nichts, und der Testserver # blockierte den halben Vormittag den VRAM. stop_testserver() { local pid i uebrig for pid in $(testserver_pids); do echo " Testserver beenden: PID $pid ($(tr '\0' ' ' < /proc/$pid/cmdline 2>/dev/null | grep -o -- '--port [0-9]*'))" kill -TERM "$pid" 2>/dev/null done for i in $(seq 1 25); do [ -z "$(testserver_pids)" ] && break; sleep 1; done for pid in $(testserver_pids); do echo " haert killen: PID $pid"; kill -9 "$pid" 2>/dev/null; done sleep 3 # Gegenprobe: bleibt ein als Testserver eingestufter Prozess uebrig, ist # der Abbau gescheitert — dann fehlt dem Produktivstack nachher der VRAM. uebrig=$(testserver_pids | tr '\n' ' ') [ -n "${uebrig// /}" ] && echo " ACHTUNG: Testserver ueberlebt den Abbau:$uebrig" return 0 }