124 lines
2.5 KiB
Bash
Executable File
124 lines
2.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
ROOT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)"
|
|
RUN_DIR="$ROOT_DIR/run"
|
|
PID_FILE="$RUN_DIR/hy-app-monitor.pid"
|
|
LOG_FILE="$RUN_DIR/hy-app-monitor.log"
|
|
ENV_FILE="${APP_ENV_FILE:-$ROOT_DIR/.env}"
|
|
SYSTEMD_SERVICE_NAME="hy-app-monitor.service"
|
|
|
|
if [ -f "$ENV_FILE" ]; then
|
|
set -a
|
|
# shellcheck disable=SC1090
|
|
. "$ENV_FILE"
|
|
set +a
|
|
fi
|
|
|
|
APP_BIND="${APP_BIND:-0.0.0.0}"
|
|
APP_PORT="${APP_PORT:-2026}"
|
|
TARGETS_FILE="${TARGETS_FILE:-$ROOT_DIR/config/targets.json}"
|
|
|
|
if [ -x "$ROOT_DIR/.venv/bin/python" ]; then
|
|
PYTHON_BIN_DEFAULT="$ROOT_DIR/.venv/bin/python"
|
|
else
|
|
PYTHON_BIN_DEFAULT="python3"
|
|
fi
|
|
|
|
PYTHON_BIN="${PYTHON_BIN:-$PYTHON_BIN_DEFAULT}"
|
|
|
|
mkdir -p "$RUN_DIR"
|
|
|
|
read_pid() {
|
|
if [ -f "$PID_FILE" ]; then
|
|
local pid
|
|
pid="$(cat "$PID_FILE")"
|
|
if pid_matches_project "$pid"; then
|
|
echo "$pid"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
discover_project_pid
|
|
}
|
|
|
|
is_running() {
|
|
local pid
|
|
pid="$(read_pid || true)"
|
|
if [ -z "${pid:-}" ]; then
|
|
rm -f "$PID_FILE"
|
|
return 1
|
|
fi
|
|
if ! kill -0 "$pid" >/dev/null 2>&1; then
|
|
rm -f "$PID_FILE"
|
|
return 1
|
|
fi
|
|
|
|
echo "$pid" >"$PID_FILE"
|
|
return 0
|
|
}
|
|
|
|
has_systemd_unit() {
|
|
if ! command -v systemctl >/dev/null 2>&1; then
|
|
return 1
|
|
fi
|
|
systemctl cat "$SYSTEMD_SERVICE_NAME" >/dev/null 2>&1
|
|
}
|
|
|
|
stop_legacy_process() {
|
|
local pid
|
|
pid="$(read_pid || true)"
|
|
|
|
if [ -n "${pid:-}" ] && kill -0 "$pid" >/dev/null 2>&1; then
|
|
kill "$pid" >/dev/null 2>&1 || true
|
|
for _ in $(seq 1 10); do
|
|
if ! kill -0 "$pid" >/dev/null 2>&1; then
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
kill -9 "$pid" >/dev/null 2>&1 || true
|
|
fi
|
|
|
|
rm -f "$PID_FILE"
|
|
}
|
|
|
|
discover_project_pid() {
|
|
if ! command -v lsof >/dev/null 2>&1; then
|
|
return 1
|
|
fi
|
|
|
|
local pid
|
|
while IFS= read -r pid; do
|
|
if pid_matches_project "$pid"; then
|
|
echo "$pid"
|
|
return 0
|
|
fi
|
|
done < <(lsof -tiTCP:"$APP_PORT" -sTCP:LISTEN 2>/dev/null || true)
|
|
|
|
return 1
|
|
}
|
|
|
|
pid_matches_project() {
|
|
local pid="$1"
|
|
if [ -z "${pid:-}" ] || ! kill -0 "$pid" >/dev/null 2>&1; then
|
|
return 1
|
|
fi
|
|
|
|
local command
|
|
command="$(ps -p "$pid" -o command= 2>/dev/null || true)"
|
|
if [[ "$command" != *"$ROOT_DIR/server.py"* ]] && [[ "$command" != *" server.py"* ]]; then
|
|
return 1
|
|
fi
|
|
|
|
if command -v lsof >/dev/null 2>&1; then
|
|
local cwd
|
|
cwd="$(lsof -a -p "$pid" -d cwd -Fn 2>/dev/null | sed -n 's/^n//p' | head -n 1)"
|
|
if [ -n "$cwd" ] && [ "$cwd" != "$ROOT_DIR" ]; then
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
return 0
|
|
}
|