govon-runtime / scripts /govon-bootstrap.sh
umyunsang's picture
sync: scripts/ (verify_e2e_tool_calling.py)
769e684 verified
#!/usr/bin/env bash
# GovOn daemon bootstrap script
# Usage: ./scripts/govon-bootstrap.sh [start|stop|status|health]
#
# ํ™˜๊ฒฝ๋ณ€์ˆ˜:
# GOVON_HOME โ€” GovOn ํ™ˆ ๋””๋ ‰ํ„ฐ๋ฆฌ (๊ธฐ๋ณธ: ~/.govon)
# GOVON_PORT โ€” daemon ํฌํŠธ (๊ธฐ๋ณธ: 8000)
# SKIP_MODEL_LOAD โ€” ๋ชจ๋ธ ๋กœ๋“œ ๊ฑด๋„ˆ๋›ฐ๊ธฐ (๊ฒฝ๊ณ  ํ‘œ์‹œ๋จ)
set -euo pipefail
PYTHON_CMD=""
# ---------------------------------------------------------------------------
# ์„ค์ •
# ---------------------------------------------------------------------------
GOVON_HOME="${GOVON_HOME:-$HOME/.govon}"
GOVON_PORT="${GOVON_PORT:-8000}"
HEALTH_URL="http://127.0.0.1:${GOVON_PORT}/health"
PID_FILE="${GOVON_HOME}/daemon.pid"
LOG_FILE="${GOVON_HOME}/daemon.log"
# ---------------------------------------------------------------------------
# ์ƒ‰์ƒ ์ถœ๋ ฅ ํ—ฌํผ
# ---------------------------------------------------------------------------
_info() { echo "[INFO] $*"; }
_warn() { echo "[WARN] $*" >&2; }
_error() { echo "[ERROR] $*" >&2; }
_success() { echo "[OK] $*"; }
# ---------------------------------------------------------------------------
# Pre-flight ๊ฒ€์‚ฌ
# ---------------------------------------------------------------------------
_preflight_checks() {
# SKIP_MODEL_LOAD ๊ฒฝ๊ณ 
if [ "${SKIP_MODEL_LOAD:-}" = "true" ] || [ "${SKIP_MODEL_LOAD:-}" = "1" ]; then
_warn "SKIP_MODEL_LOAD๊ฐ€ ์„ค์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋ธ์ด ๋กœ๋“œ๋˜์ง€ ์•Š์œผ๋ฉฐ ์ผ๋ถ€ ๊ธฐ๋Šฅ์ด ๋น„ํ™œ์„ฑํ™”๋ฉ๋‹ˆ๋‹ค."
fi
# GPU ๊ฐ์ง€ ๊ฒฝ๊ณ 
if command -v nvidia-smi &>/dev/null; then
if ! nvidia-smi &>/dev/null 2>&1; then
_warn "nvidia-smi ์‹คํ–‰์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค. GPU๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค."
fi
else
_warn "nvidia-smi๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. CPU ์ „์šฉ ๋ชจ๋“œ๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. (์„ฑ๋Šฅ์ด ํฌ๊ฒŒ ์ €ํ•˜๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค)"
fi
}
# ---------------------------------------------------------------------------
# Python / govon ์„ค์น˜ ํ™•์ธ
# ---------------------------------------------------------------------------
_check_python() {
if ! command -v python3 &>/dev/null && ! command -v python &>/dev/null; then
_error "Python์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. Python 3.10 ์ด์ƒ์„ ์„ค์น˜ํ•˜์„ธ์š”."
exit 1
fi
PYTHON_CMD="$(command -v python3 || command -v python)"
_info "Python: $("$PYTHON_CMD" --version 2>&1)"
}
_check_govon() {
# govon CLI ๋˜๋Š” src.cli.shell ๋ชจ๋“ˆ ๊ฐ€์šฉ ์—ฌ๋ถ€ ํ™•์ธ
if command -v govon &>/dev/null; then
GOVON_CMD="govon"
_info "govon ๋ช…๋ น์–ด ๋ฐœ๊ฒฌ: $(command -v govon)"
elif $PYTHON_CMD -c "import src.cli.shell" 2>/dev/null; then
GOVON_CMD="$PYTHON_CMD -m src.cli.shell"
_info "govon ๋ชจ๋“ˆ(src.cli.shell) ๋ฐœ๊ฒฌ"
else
_error "govon์ด ์„ค์น˜๋˜์–ด ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. 'pip install govon[cli]' ๋˜๋Š” 'pip install -e .[cli]'๋ฅผ ์‹คํ–‰ํ•˜์„ธ์š”."
exit 1
fi
}
# ---------------------------------------------------------------------------
# PID ์œ ํ‹ธ๋ฆฌํ‹ฐ
# ---------------------------------------------------------------------------
_read_pid() {
if [ -f "$PID_FILE" ]; then
awk '{print $1}' "$PID_FILE" 2>/dev/null || echo ""
fi
}
_pid_alive() {
local pid="$1"
[ -n "$pid" ] && kill -0 "$pid" 2>/dev/null
}
# ---------------------------------------------------------------------------
# health ํ™•์ธ
# ---------------------------------------------------------------------------
_health_check() {
curl -sf --max-time 5 "$HEALTH_URL" &>/dev/null
}
# ---------------------------------------------------------------------------
# ๋ช…๋ น: start
# ---------------------------------------------------------------------------
cmd_start() {
_preflight_checks
_check_python
_check_govon
# ์ด๋ฏธ ์‹คํ–‰ ์ค‘์ธ์ง€ ํ™•์ธ
local existing_pid
existing_pid="$(_read_pid)"
if _pid_alive "$existing_pid" && _health_check; then
_success "GovOn daemon์ด ์ด๋ฏธ ์‹คํ–‰ ์ค‘์ž…๋‹ˆ๋‹ค. (PID=$existing_pid, ํฌํŠธ=$GOVON_PORT)"
exit 0
fi
# ~/.govon ๋””๋ ‰ํ„ฐ๋ฆฌ ์ƒ์„ฑ
mkdir -p "$GOVON_HOME"
_info "GovOn daemon์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. (ํฌํŠธ=$GOVON_PORT, ๋กœ๊ทธ=$LOG_FILE)"
# daemon ๊ธฐ๋™
if [ "$GOVON_CMD" = "govon" ]; then
# govon CLI๋ฅผ ํ†ตํ•œ ๊ธฐ๋™ (govon --start ์ง€์› ์‹œ ์‚ฌ์šฉ; ์—†์œผ๋ฉด ์ง์ ‘ uvicorn ํ˜ธ์ถœ)
if govon --help 2>&1 | grep -q -- "--start" 2>/dev/null; then
govon --start >> "$LOG_FILE" 2>&1 &
else
# ์ง์ ‘ uvicorn์œผ๋กœ ๊ธฐ๋™
$PYTHON_CMD -m uvicorn src.inference.api_server:app \
--host 127.0.0.1 \
--port "$GOVON_PORT" >> "$LOG_FILE" 2>&1 &
fi
else
$PYTHON_CMD -m uvicorn src.inference.api_server:app \
--host 127.0.0.1 \
--port "$GOVON_PORT" >> "$LOG_FILE" 2>&1 &
fi
local daemon_pid=$!
echo "$daemon_pid $(date +%s)" > "$PID_FILE"
_info "daemon PID=$daemon_pid ๊ธฐ๋ก ์™„๋ฃŒ."
# ๋น ๋ฅธ ์‹คํŒจ ๊ฐ์ง€: 2์ดˆ ํ›„ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ด๋ฏธ ์ข…๋ฃŒ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ
sleep 2
if ! kill -0 "$daemon_pid" 2>/dev/null; then
_error "daemon์ด ๊ธฐ๋™ ์งํ›„ ์ข…๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋กœ๊ทธ๋ฅผ ํ™•์ธํ•˜์„ธ์š”: $LOG_FILE"
rm -f "$PID_FILE"
exit 1
fi
# health check ๋Œ€๊ธฐ (์ตœ๋Œ€ 120์ดˆ)
local elapsed=0
local max_wait=120
_info "health check ๋Œ€๊ธฐ ์ค‘..."
while [ $elapsed -lt $max_wait ]; do
if _health_check; then
_success "GovOn daemon ๊ธฐ๋™ ์™„๋ฃŒ. (PID=$daemon_pid, ํฌํŠธ=$GOVON_PORT)"
exit 0
fi
sleep 1
elapsed=$((elapsed + 1))
done
_error "health check timeout (${max_wait}s). ๋กœ๊ทธ๋ฅผ ํ™•์ธํ•˜์„ธ์š”: $LOG_FILE"
exit 1
}
# ---------------------------------------------------------------------------
# ๋ช…๋ น: stop
# ---------------------------------------------------------------------------
cmd_stop() {
local pid
pid="$(_read_pid)"
if [ -z "$pid" ]; then
_warn "PID ํŒŒ์ผ์ด ์—†์Šต๋‹ˆ๋‹ค. daemon์ด ์‹คํ–‰ ์ค‘์ด ์•„๋‹Œ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผํ•ฉ๋‹ˆ๋‹ค."
exit 0
fi
if ! _pid_alive "$pid"; then
_warn "PID=$pid ํ”„๋กœ์„ธ์Šค๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. PID ํŒŒ์ผ์„ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค."
rm -f "$PID_FILE"
exit 0
fi
# govon CLI --stop ์ง€์› ์—ฌ๋ถ€ ํ™•์ธ
if command -v govon &>/dev/null && govon --help 2>&1 | grep -q -- "--stop" 2>/dev/null; then
govon --stop
else
_info "SIGTERM ์ „์†ก: PID=$pid"
kill -TERM "$pid"
local elapsed=0
while [ $elapsed -lt 10 ]; do
if ! _pid_alive "$pid"; then
_success "GovOn daemon์ด ์ •์ƒ ์ข…๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. (PID=$pid)"
rm -f "$PID_FILE"
exit 0
fi
sleep 1
elapsed=$((elapsed + 1))
done
_warn "timeout โ€” SIGKILL ์ „์†ก: PID=$pid"
kill -KILL "$pid" 2>/dev/null || true
rm -f "$PID_FILE"
_success "GovOn daemon์ด ๊ฐ•์ œ ์ข…๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. (PID=$pid)"
fi
}
# ---------------------------------------------------------------------------
# ๋ช…๋ น: status
# ---------------------------------------------------------------------------
cmd_status() {
local pid
pid="$(_read_pid)"
if [ -z "$pid" ]; then
echo "GovOn daemon: ์ค‘์ง€๋จ (PID ํŒŒ์ผ ์—†์Œ)"
exit 1
fi
if ! _pid_alive "$pid"; then
echo "GovOn daemon: ์ค‘์ง€๋จ (PID=$pid โ€” ํ”„๋กœ์„ธ์Šค ์—†์Œ)"
rm -f "$PID_FILE"
exit 1
fi
if _health_check; then
echo "GovOn daemon: ์‹คํ–‰ ์ค‘ (PID=$pid, ํฌํŠธ=$GOVON_PORT)"
exit 0
else
echo "GovOn daemon: ํ”„๋กœ์„ธ์Šค๋Š” ์‚ด์•„ ์žˆ์ง€๋งŒ health check ์‹คํŒจ (PID=$pid, URL=$HEALTH_URL)"
exit 2
fi
}
# ---------------------------------------------------------------------------
# ๋ช…๋ น: health
# ---------------------------------------------------------------------------
cmd_health() {
_info "GET $HEALTH_URL"
if curl -sf --max-time 10 "$HEALTH_URL"; then
echo ""
_success "health check ํ†ต๊ณผ."
exit 0
else
_error "health check ์‹คํŒจ. daemon์ด ์‹คํ–‰ ์ค‘์ธ์ง€ ํ™•์ธํ•˜์„ธ์š”."
exit 1
fi
}
# ---------------------------------------------------------------------------
# ์ง„์ž…์ 
# ---------------------------------------------------------------------------
COMMAND="${1:-help}"
case "$COMMAND" in
start)
cmd_start
;;
stop)
cmd_stop
;;
status)
cmd_status
;;
health)
cmd_health
;;
help|--help|-h)
echo "์‚ฌ์šฉ๋ฒ•: $0 [start|stop|status|health]"
echo ""
echo "๋ช…๋ น์–ด:"
echo " start โ€” GovOn daemon์„ ๊ธฐ๋™ํ•ฉ๋‹ˆ๋‹ค"
echo " stop โ€” GovOn daemon์„ ์ค‘์ง€ํ•ฉ๋‹ˆ๋‹ค"
echo " status โ€” daemon ์‹คํ–‰ ์ƒํƒœ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค"
echo " health โ€” /health ์—”๋“œํฌ์ธํŠธ๋ฅผ probeํ•ฉ๋‹ˆ๋‹ค"
echo ""
echo "ํ™˜๊ฒฝ๋ณ€์ˆ˜:"
echo " GOVON_HOME=$GOVON_HOME"
echo " GOVON_PORT=$GOVON_PORT"
echo " SKIP_MODEL_LOAD (์„ค์ • ์‹œ ๊ฒฝ๊ณ  ํ‘œ์‹œ)"
exit 0
;;
*)
_error "์•Œ ์ˆ˜ ์—†๋Š” ๋ช…๋ น: $COMMAND"
echo "์‚ฌ์šฉ๋ฒ•: $0 [start|stop|status|health]"
exit 1
;;
esac