2026-08-13 16:23:18 +04:00

42 lines
1.5 KiB
Bash

#!/usr/bin/env bash
# Idempotent starter for the X2 dashboard agent.
#
# Run this every minute from cron. If the agent is already up it does nothing;
# if it is not, it starts it. That covers three cases with one mechanism:
# * boot - the robot came back and nobody logged in
# * crash - the process died
# * manual kill - someone stopped it by hand
#
# Why not systemd? The agi account cannot enable linger (`loginctl
# enable-linger` is denied, and sudo forbids running as root here), so a
# `systemd --user` unit only runs while a login session exists - which is
# exactly not the case after a power cycle. A cron watchdog needs no root and
# does not depend on @reboot firing correctly.
set -e
DIR="$(dirname "$(readlink -f "$0")")"
PORT="${X2_AGENT_PORT:-8781}"
LOG="$DIR/agent.log"
# Already listening? Nothing to do. Checking the port rather than the process
# also catches a process that is alive but wedged before binding.
if ss -ltn 2>/dev/null | grep -q ":${PORT} "; then
exit 0
fi
# Avoid stacking instances if a previous start is still coming up.
if pgrep -f "x2_agent.py" >/dev/null 2>&1; then
exit 0
fi
echo "[$(date -Is)] agent not listening on ${PORT} - starting" >> "$LOG"
# Keep the log from growing without bound (cron runs this every minute).
if [ -f "$LOG" ] && [ "$(stat -c%s "$LOG" 2>/dev/null || echo 0)" -gt 1000000 ]; then
tail -n 200 "$LOG" > "$LOG.tmp" && mv "$LOG.tmp" "$LOG"
fi
setsid nohup "$DIR/run_agent.sh" >> "$LOG" 2>&1 < /dev/null &
exit 0