153 lines
4.0 KiB
Bash
Executable File
153 lines
4.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
VENV_DIR="${FGAI_VENV_DIR:-$ROOT_DIR/.venv}"
|
|
PORT="${FGAI_SYSLOG_PORT:-5514}"
|
|
HOST="${FGAI_SYSLOG_HOST:-0.0.0.0}"
|
|
LOG_FILE="${FGAI_SYSLOG_FILE:-$ROOT_DIR/logs/fg_syslog.jsonl}"
|
|
LISTENER_LOG="${FGAI_LISTENER_LOG:-$ROOT_DIR/logs/fgai-listener.log}"
|
|
PID_FILE="${FGAI_PID_FILE:-$ROOT_DIR/run/fgai-listener.pid}"
|
|
|
|
usage() {
|
|
printf 'Usage: %s [start|stop|restart|status|tail|analyze|install]\n' "$0"
|
|
printf '\nDefault action: start\n'
|
|
printf '\nEnvironment overrides:\n'
|
|
printf ' FGAI_SYSLOG_PORT=%s\n' "$PORT"
|
|
printf ' FGAI_SYSLOG_HOST=%s\n' "$HOST"
|
|
printf ' FGAI_SYSLOG_FILE=%s\n' "$LOG_FILE"
|
|
printf ' FGAI_LISTENER_LOG=%s\n' "$LISTENER_LOG"
|
|
}
|
|
|
|
activate_venv_for_script() {
|
|
# Activation here affects this script process. It cannot modify the parent shell prompt.
|
|
# Use "source .venv/bin/activate" manually if you want your interactive prompt to show it.
|
|
# shellcheck disable=SC1091
|
|
source "$VENV_DIR/bin/activate"
|
|
}
|
|
|
|
install_deps() {
|
|
if [ ! -x "$VENV_DIR/bin/python" ]; then
|
|
printf 'Creating venv: %s\n' "$VENV_DIR"
|
|
python3 -m venv "$VENV_DIR"
|
|
fi
|
|
|
|
activate_venv_for_script
|
|
printf 'Installing/updating fgAI dependencies...\n'
|
|
python -m pip install --upgrade pip
|
|
python -m pip install -e "$ROOT_DIR"
|
|
}
|
|
|
|
is_running() {
|
|
[ -f "$PID_FILE" ] && ps -p "$(cat "$PID_FILE")" >/dev/null 2>&1
|
|
}
|
|
|
|
needs_privileged_port() {
|
|
[ "$PORT" -lt 1024 ] && [ "${EUID:-$(id -u)}" -ne 0 ]
|
|
}
|
|
|
|
listener_command() {
|
|
"$VENV_DIR/bin/fgai" listen-syslog \
|
|
--host "$HOST" \
|
|
--port "$PORT" \
|
|
--output "$LOG_FILE" \
|
|
--quiet
|
|
}
|
|
|
|
start_listener() {
|
|
install_deps
|
|
mkdir -p "$(dirname "$LOG_FILE")" "$(dirname "$LISTENER_LOG")" "$(dirname "$PID_FILE")"
|
|
touch "$LOG_FILE"
|
|
|
|
if is_running; then
|
|
printf 'fgAI syslog listener already running, pid %s\n' "$(cat "$PID_FILE")"
|
|
return 0
|
|
fi
|
|
|
|
if needs_privileged_port; then
|
|
printf 'Port %s needs elevated privileges; starting listener with sudo.\n' "$PORT"
|
|
sudo nohup "$VENV_DIR/bin/fgai" listen-syslog \
|
|
--host "$HOST" \
|
|
--port "$PORT" \
|
|
--output "$LOG_FILE" \
|
|
--quiet > "$LISTENER_LOG" 2>&1 &
|
|
else
|
|
nohup "$VENV_DIR/bin/fgai" listen-syslog \
|
|
--host "$HOST" \
|
|
--port "$PORT" \
|
|
--output "$LOG_FILE" \
|
|
--quiet > "$LISTENER_LOG" 2>&1 &
|
|
fi
|
|
printf '%s\n' "$!" > "$PID_FILE"
|
|
|
|
printf 'Started fgAI syslog listener, pid %s\n' "$(cat "$PID_FILE")"
|
|
printf 'Input: udp://%s:%s\n' "$HOST" "$PORT"
|
|
printf 'Syslog file: %s\n' "$LOG_FILE"
|
|
printf 'Process log: %s\n' "$LISTENER_LOG"
|
|
}
|
|
|
|
stop_listener() {
|
|
if ! is_running; then
|
|
printf 'fgAI syslog listener is not running\n'
|
|
rm -f "$PID_FILE"
|
|
return 0
|
|
fi
|
|
|
|
if ! kill "$(cat "$PID_FILE")" 2>/dev/null; then
|
|
sudo kill "$(cat "$PID_FILE")"
|
|
fi
|
|
rm -f "$PID_FILE"
|
|
printf 'Stopped fgAI syslog listener\n'
|
|
}
|
|
|
|
status_listener() {
|
|
if is_running; then
|
|
printf 'fgAI syslog listener running, pid %s\n' "$(cat "$PID_FILE")"
|
|
printf 'Input: udp://%s:%s\n' "$HOST" "$PORT"
|
|
printf 'Syslog file: %s\n' "$LOG_FILE"
|
|
if command -v ss >/dev/null 2>&1; then
|
|
ss -lunp 2>/dev/null | awk -v port=":$PORT" '$0 ~ port {print}'
|
|
fi
|
|
return 0
|
|
fi
|
|
|
|
printf 'fgAI syslog listener is not running\n'
|
|
return 1
|
|
}
|
|
|
|
command="${1:-start}"
|
|
case "$command" in
|
|
start)
|
|
start_listener
|
|
;;
|
|
stop)
|
|
stop_listener
|
|
;;
|
|
restart)
|
|
stop_listener
|
|
start_listener
|
|
;;
|
|
status)
|
|
status_listener
|
|
;;
|
|
tail)
|
|
mkdir -p "$(dirname "$LOG_FILE")"
|
|
touch "$LOG_FILE"
|
|
tail -f "$LOG_FILE"
|
|
;;
|
|
analyze)
|
|
install_deps
|
|
fgai analyze-logs --logs "$LOG_FILE"
|
|
;;
|
|
install)
|
|
install_deps
|
|
;;
|
|
-h|--help|help)
|
|
usage
|
|
;;
|
|
*)
|
|
usage
|
|
exit 2
|
|
;;
|
|
esac
|