added stop-skript

This commit is contained in:
Alexander Gabriel 2026-10-18 15:16:43 +02:00
parent 4e7f9425e3
commit 3eacfa2a75
2 changed files with 86 additions and 2 deletions

View File

@ -48,6 +48,16 @@ sudo ./scripts/firewall-ufw.sh # einmalig: Ports 8800 + 8801 für LAN + wt0 in
**Nach einem Reboot** startet der Stack von selbst: Der Docker-Dienst ist aktiviert, und die Container haben `restart: unless-stopped`. Autocomplete und Embeddings lädt llama-swap per `hooks.on_startup.preload` ebenfalls von selbst, das Chat-Modell kommt beim ersten Request dazu.
Gestoppt bzw. der VRAM freigegeben wird mit `scripts/stop.sh`. Laufen Modelle, entlädt das Skript sie vorher über llama-swap, damit die Server sauber beendet werden. Danach zeigt es Container-Status und VRAM-Belegung.
| Aufruf | Wirkung |
|---|---|
| `./scripts/stop.sh` | Modelle entladen, Container stoppen (bleiben auch nach einem Reboot aus) |
| `./scripts/stop.sh --unload` | nur alle Modelle entladen, Container laufen weiter |
| `./scripts/stop.sh --down` | Container stoppen und entfernen, Modelle und Daten bleiben erhalten |
Nach dem Stoppen (mit oder ohne `--down`) startet `./scripts/start.sh` den Stack wieder. Nach `--unload` lädt llama-swap Autocomplete und Embeddings beim nächsten Request von selbst neu.
Der erste Aufruf eines Modells lädt es von Hugging Face herunter (Hauptmodell ~22 GB). Danach läuft alles offline.
Whisper und das Bildmodell lädt llama-swap **nicht** selbst herunter (~12 GB):
@ -140,6 +150,5 @@ GPU-Layer und MoE-Auslagerung in den RAM verteilt llama.cpp automatisch (`--fit`
| `client/continue/` | Vorlage für Continue-Clients |
| `docs/laravel.md` | Anbindung einer Laravel-App (laravel/ai) |
| `scripts/start.sh` | Start mit Prüfungen, Preload und Statusausgabe |
| `scripts/stop.sh` | Stoppen bzw. Modelle entladen, mit Statusausgabe |
| `scripts/firewall-ufw.sh` | ufw-Freigaben |
| `PLAN.md` | ursprünglicher Umsetzungsplan |
| `PLAN-multimodal.md` | Plan + Messwerte für Transkription/Bilder |

75
scripts/stop.sh Executable file
View File

@ -0,0 +1,75 @@
#!/usr/bin/env bash
# Stoppt den LocalAI-Stack bzw. gibt den VRAM frei.
#
# ./scripts/stop.sh Container stoppen (bleiben auch nach Reboot aus)
# ./scripts/stop.sh --unload nur alle Modelle entladen, Container laufen weiter
# ./scripts/stop.sh --down Container stoppen und entfernen (Modelle/Daten bleiben)
set -euo pipefail
cd "$(dirname "$(readlink -f "$0")")/.."
MODE=stop
while [[ $# -gt 0 ]]; do
case "$1" in
--unload) MODE=unload ;;
--down) MODE=down ;;
-h|--help) sed -n '2,6p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
*) echo "Unbekannte Option: $1" >&2; exit 2 ;;
esac
shift
done
if [[ -t 1 ]]; then B=$'\e[1m'; G=$'\e[32m'; Y=$'\e[33m'; R=$'\e[31m'; N=$'\e[0m'; else B= G= Y= R= N=; fi
ok() { echo "${G}✔${N} $*"; }
warn() { echo "${Y}!${N} $*"; }
die() { echo "${R}✘${N} $*" >&2; exit 1; }
step() { echo; echo "${B}== $*${N}"; }
command -v docker >/dev/null || die "docker nicht installiert"
docker info >/dev/null 2>&1 || die "Docker-Daemon läuft nicht oder keine Rechte (Gruppe 'docker'?)"
BACKEND_PORT=8080
[[ -f .env ]] && BACKEND_PORT=$(set -a; . ./.env; echo "${BACKEND_PORT:-8080}")
running=$(docker compose ps --status running -q 2>/dev/null | wc -l)
# ------------------------------------------------------------- Entladen
# vor dem Stoppen entladen, damit llama-swap die Server sauber beendet
if [[ "$running" -gt 0 ]] && curl -fsS -m 2 "http://127.0.0.1:$BACKEND_PORT/health" >/dev/null 2>&1; then
step "Entlade Modelle"
loaded=$(curl -s -m 5 "http://127.0.0.1:$BACKEND_PORT/running" \
| python3 -c 'import sys,json; print(", ".join(m["model"] for m in json.load(sys.stdin)["running"]) or "-")' 2>/dev/null || echo "?")
echo " geladen: $loaded"
if curl -fsS -m 60 -o /dev/null "http://127.0.0.1:$BACKEND_PORT/unload"; then
ok "Modelle entladen"
else
warn "Entladen über llama-swap fehlgeschlagen"
fi
elif [[ "$MODE" == unload ]]; then
die "llama-swap läuft nicht – nichts zu entladen"
fi
# --------------------------------------------------------------- Stoppen
case "$MODE" in
stop)
step "Stoppe Container"
docker compose stop
ok "Stack gestoppt – Neustart mit ./scripts/start.sh"
;;
down)
step "Stoppe und entferne Container"
docker compose down --remove-orphans
ok "Stack entfernt – Neustart mit ./scripts/start.sh"
;;
unload)
warn "Container laufen weiter – Autocomplete/Embeddings werden beim nächsten Request neu geladen"
;;
esac
# ------------------------------------------------------------------ Status
step "Status"
docker compose ps -a --format '{{.Service}}: {{.Status}}' | sed 's/^/ /'
[[ "$(docker compose ps -a -q | wc -l)" -eq 0 ]] && echo " keine Container"
command -v rocm-smi >/dev/null && rocm-smi --showmeminfo vram 2>/dev/null \
| awk '/GPU\[0\].*Total Memory/{t=$NF} /GPU\[0\].*Used Memory/{u=$NF} END{if(t) printf " VRAM: %.1f / %.1f GB\n", u/1e9, t/1e9}'
true