109 lines
3.3 KiB
Bash
Executable File
109 lines
3.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Podgląd logów backendu LLM - jedno wejście niezależnie od tego, czy backend
|
|
# działa w kontenerze (vllm-gpu) czy jako proces z plikiem logu (vllm-metal, ollama, mock).
|
|
#
|
|
# Użycie:
|
|
# logs.sh --backend vllm-gpu [--tail 100] [--follow|--no-follow] [--grep WZORZEC] [--save PLIK]
|
|
#
|
|
# Domyślnie śledzi na bieżąco (jak `tail -f`). --no-follow robi jednorazowy zrzut,
|
|
# co jest tym, czego się chce przy wklejaniu fragmentu do zgłoszenia.
|
|
set -euo pipefail
|
|
|
|
# Ctrl-C przy śledzeniu logów to normalne zakończenie, nie awaria - bez tego
|
|
# go-task raportowałby "Failed to run task" za każdym razem, gdy ktoś przerwie podgląd.
|
|
trap 'exit 0' INT TERM
|
|
|
|
BACKEND=""
|
|
RUN_DIR=".runs/llm"
|
|
TAIL="100"
|
|
FOLLOW="true"
|
|
PATTERN=""
|
|
SAVE=""
|
|
COMPOSE_FILE="llm/docker-compose.yml"
|
|
|
|
usage() { sed -n '2,12p' "$0" >&2; exit "${1:-1}"; }
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--backend) BACKEND="${2:?}"; shift 2 ;;
|
|
--run-dir) RUN_DIR="${2:?}"; shift 2 ;;
|
|
--tail) TAIL="${2:?}"; shift 2 ;;
|
|
--grep) PATTERN="${2:?}"; shift 2 ;;
|
|
--save) SAVE="${2:?}"; shift 2 ;;
|
|
--follow) FOLLOW="true"; shift ;;
|
|
--no-follow) FOLLOW="false"; shift ;;
|
|
-h|--help) usage 0 ;;
|
|
*) echo "nieznany argument: $1" >&2; usage ;;
|
|
esac
|
|
done
|
|
|
|
[ -n "$BACKEND" ] || { echo "podaj --backend" >&2; exit 1; }
|
|
# Zapis do pliku bez sensu w trybie śledzenia - zrzut ma się skończyć.
|
|
[ -n "$SAVE" ] && FOLLOW="false"
|
|
|
|
log_file_for() {
|
|
case "$1" in
|
|
vllm-metal) echo "$RUN_DIR/vllm-metal.log" ;;
|
|
ollama) echo "$RUN_DIR/ollama.log" ;;
|
|
mock) echo "$RUN_DIR/mock.log" ;;
|
|
*) echo "" ;;
|
|
esac
|
|
}
|
|
|
|
# Strumień logów na stdout, zależnie od backendu.
|
|
emit() {
|
|
if [ "$BACKEND" = "vllm-gpu" ]; then
|
|
command -v docker >/dev/null 2>&1 || { echo "brak dockera - a backend vllm-gpu działa w kontenerze" >&2; exit 1; }
|
|
if [ "$FOLLOW" = "true" ]; then
|
|
docker compose -f "$COMPOSE_FILE" --profile vllm-gpu logs --follow --tail "$TAIL"
|
|
else
|
|
docker compose -f "$COMPOSE_FILE" --profile vllm-gpu logs --tail "$TAIL"
|
|
fi
|
|
return
|
|
fi
|
|
|
|
local file
|
|
file="$(log_file_for "$BACKEND")"
|
|
if [ -z "$file" ]; then
|
|
echo "backend '$BACKEND' nie ma znanego źródła logów" >&2
|
|
exit 1
|
|
fi
|
|
if [ ! -f "$file" ]; then
|
|
echo "brak pliku logu: $file" >&2
|
|
echo "backend prawdopodobnie nie był uruchamiany - zacznij od: task llm:up" >&2
|
|
exit 1
|
|
fi
|
|
if [ "$FOLLOW" = "true" ]; then
|
|
# --follow=name odtwarza plik po rotacji/nadpisaniu, np. przy restarcie backendu
|
|
tail -n "$TAIL" -F "$file"
|
|
else
|
|
tail -n "$TAIL" "$file"
|
|
fi
|
|
}
|
|
|
|
filter() {
|
|
if [ -n "$PATTERN" ]; then
|
|
# --line-buffered: przy śledzeniu linie mają się pojawiać od razu, a nie po zapełnieniu bufora
|
|
grep --line-buffered -Ei "$PATTERN" || true
|
|
else
|
|
cat
|
|
fi
|
|
}
|
|
|
|
if [ -n "$SAVE" ]; then
|
|
mkdir -p "$(dirname "$SAVE")"
|
|
emit | filter > "$SAVE"
|
|
echo "zapisano $(wc -l < "$SAVE" | tr -d ' ') linii do $SAVE"
|
|
elif [ "$FOLLOW" = "true" ]; then
|
|
emit | filter
|
|
else
|
|
# Jednorazowy zrzut: pusty wynik przy filtrze jest dwuznaczny (brak dopasowań
|
|
# czy brak logów?), więc mówimy to wprost zamiast milczeć.
|
|
output="$(emit | filter)"
|
|
if [ -z "$output" ] && [ -n "$PATTERN" ]; then
|
|
echo "brak linii pasujących do '$PATTERN' w ostatnich $TAIL liniach logu" >&2
|
|
else
|
|
printf '%s\n' "$output"
|
|
fi
|
|
fi
|