359afb3a59
Infrastructure configs for GMKtec K11 (Docker, vLLM, LocalAI, ComfyUI, control-plane, gpu-fan agent, Server UI with CLI/file explorer/GPU fan curve). Co-authored-by: Cursor <cursoragent@cursor.com>
84 lines
2.3 KiB
Bash
Executable File
84 lines
2.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
STACK_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
|
CONTROL_PLANE_ENV="${STACK_DIR}/../control-plane/.env"
|
|
EXAMPLE="${STACK_DIR}/../control-plane/.env.example"
|
|
|
|
cd "${STACK_DIR}"
|
|
|
|
if [[ ! -f "${CONTROL_PLANE_ENV}" ]]; then
|
|
cp "${EXAMPLE}" "${CONTROL_PLANE_ENV}"
|
|
echo "Created ${CONTROL_PLANE_ENV} from example"
|
|
fi
|
|
|
|
set -a
|
|
# shellcheck disable=SC1091
|
|
source "${CONTROL_PLANE_ENV}"
|
|
set +a
|
|
|
|
export CONTROL_PLANE_ENV="${CONTROL_PLANE_ENV}"
|
|
|
|
CURVE_PATH="${CURVE_PATH:-/etc/gpu-fan/curve.json}"
|
|
export CURVE_PATH
|
|
|
|
if [[ ! -f "${CURVE_PATH}" ]]; then
|
|
if [[ "${EUID}" -eq 0 ]]; then
|
|
mkdir -p "$(dirname "${CURVE_PATH}")"
|
|
cp curve.default.json "${CURVE_PATH}"
|
|
else
|
|
mkdir -p "${STACK_DIR}/config"
|
|
CURVE_PATH="${STACK_DIR}/config/curve.json"
|
|
export CURVE_PATH
|
|
[[ -f "${CURVE_PATH}" ]] || cp curve.default.json "${CURVE_PATH}"
|
|
echo "Using local curve: ${CURVE_PATH}"
|
|
fi
|
|
fi
|
|
|
|
if [[ ! -d .venv ]]; then
|
|
python3 -m venv .venv
|
|
.venv/bin/pip install -q -r requirements.txt
|
|
fi
|
|
|
|
if [[ "${EUID}" -ne 0 ]]; then
|
|
echo "ERROR: Fan control requires root. Use:"
|
|
echo " sudo -E ${SCRIPT_DIR}/start.sh"
|
|
echo "Or install system-wide:"
|
|
echo " sudo ${SCRIPT_DIR}/install.sh && sudo systemctl start gpu-fan"
|
|
exit 1
|
|
fi
|
|
|
|
if systemctl is-active --quiet gpu-fan 2>/dev/null; then
|
|
echo "ERROR: gpu-fan.service is already running (systemd)."
|
|
echo " Use: sudo systemctl stop gpu-fan"
|
|
echo " Or: sudo journalctl -u gpu-fan -f"
|
|
echo ""
|
|
echo "Do not run scripts/start.sh alongside systemd — one instance only."
|
|
exit 1
|
|
fi
|
|
|
|
PORT="${GPU_FAN_API_PORT:-18090}"
|
|
HOST="${GPU_FAN_API_HOST:-127.0.0.1}"
|
|
|
|
if ss -tln "sport = :${PORT}" 2>/dev/null | grep -q LISTEN; then
|
|
echo "ERROR: Port ${PORT} is already in use."
|
|
echo ""
|
|
ss -tlnp "sport = :${PORT}" 2>/dev/null || ss -tln "sport = :${PORT}"
|
|
echo ""
|
|
echo "Common causes:"
|
|
echo " - Suspended foreground start (Ctrl+Z) — run: jobs -l && kill %<n>"
|
|
echo " - Orphan process — run: sudo ${SCRIPT_DIR}/status.sh"
|
|
echo " - systemd still stopping — wait a few seconds"
|
|
exit 1
|
|
fi
|
|
|
|
echo "=== GPU Fan Control (foreground) ==="
|
|
echo "Agent API: http://${HOST}:${PORT}"
|
|
echo "Curve: ${CURVE_PATH}"
|
|
echo ""
|
|
echo "Stop with Ctrl+C (not Ctrl+Z — suspended process keeps the port)."
|
|
echo ""
|
|
|
|
exec .venv/bin/python app.py
|