#!/bin/sh # --------------------------------------------------------------------------- # supervise.sh # # Keeps one process alive. There is no systemd in this container, so this is # what restarts FXServer if it crashes. # # Two details that matter for FXServer specifically: # # * It reads its console from stdin and quits the moment stdin reaches EOF, # so it is given a FIFO whose write end this script holds open forever. # That doubles as a command channel - see /opt/fivem/bin/rcon. # # * A server that dies immediately is usually failing for a reason that will # not fix itself (bad licence key, database down, Cfx rate limiting). The # restart delay backs off so a broken server does not hammer an upstream # service, and resets once it has stayed up for a while. # --------------------------------------------------------------------------- NAME="$1"; LOG="$2"; shift 2 FIFO="${FIFO:-/run/$NAME.stdin}" MIN_DELAY=5 MAX_DELAY=300 HEALTHY_AFTER=120 # seconds of uptime that count as "it actually started" mkdir -p "$(dirname "$LOG")" echo $$ > "/run/$NAME.sup.pid" [ -p "$FIFO" ] || { rm -f "$FIFO"; mkfifo "$FIFO"; } # read-write open: holds the pipe open without blocking and without a helper process exec 9<> "$FIFO" cleanup() { kill "$CHILD" 2>/dev/null rm -f "/run/$NAME.sup.pid" "/run/$NAME.child.pid" exit 0 } trap cleanup TERM INT delay=$MIN_DELAY while true; do if [ -f "$LOG" ] && [ "$(stat -c %s "$LOG")" -gt 209715200 ]; then mv "$LOG" "$LOG.1" fi echo "=== $(date -Is) starting $NAME ===" >> "$LOG" started=$(date +%s) "$@" >> "$LOG" 2>&1 <&9 & CHILD=$! echo $CHILD > "/run/$NAME.child.pid" wait $CHILD RC=$? ran=$(( $(date +%s) - started )) if [ "$ran" -ge "$HEALTHY_AFTER" ]; then delay=$MIN_DELAY else delay=$(( delay * 2 )) [ "$delay" -gt "$MAX_DELAY" ] && delay=$MAX_DELAY fi echo "=== $(date -Is) $NAME exited (rc=$RC) after ${ran}s, restarting in ${delay}s ===" >> "$LOG" sleep "$delay" done