Procházet zdrojové kódy

Ajout de 'scripts/run-steam-game'

penta před 4 týdny
rodič
revize
9d61a8ecf8
1 změnil soubory, kde provedl 144 přidání a 0 odebrání
  1. 144 0
      scripts/run-steam-game

+ 144 - 0
scripts/run-steam-game

@@ -0,0 +1,144 @@
+#!/usr/bin/env bash
+
+set -u
+
+if [[ $# -lt 2 ]]; then
+    echo "Usage: $0 <Steam AppID> <process regex>" >&2
+    exit 2
+fi
+
+APPID="$1"
+PROCESS_REGEX="$2"
+
+START_TIMEOUT="${START_TIMEOUT:-120}"
+EXIT_STABLE_TIME="${EXIT_STABLE_TIME:-3}"
+
+SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
+LOG_FILE="${SCRIPT_DIR}/steam-game.log"
+
+log() {
+    printf '[%s] [STEAM:%s] %s\n' \
+        "$(date '+%Y-%m-%d %H:%M:%S')" \
+        "${APPID}" \
+        "$*" >> "${LOG_FILE}"
+}
+
+if ! command -v steam >/dev/null 2>&1; then
+    log "ERROR: steam command not found"
+    exit 127
+fi
+
+#
+# PIDs du jeu.
+#
+# On inspecte /proc nous-mêmes afin d'éviter que pgrep -f ne matche
+# accidentellement le wrapper avec le regex passé en argument.
+#
+game_pids() {
+    local proc
+    local pid
+    local cmdline
+    local -a argv
+
+    for proc in /proc/[0-9]*; do
+        pid="${proc##*/}"
+
+        # Ne jamais nous matcher nous-mêmes.
+        [[ "${pid}" == "$$" ]] && continue
+
+        [[ -r "${proc}/cmdline" ]] || continue
+
+        argv=()
+
+        mapfile -d '' -t argv < "${proc}/cmdline" 2>/dev/null || true
+
+        [[ ${#argv[@]} -gt 0 ]] || continue
+
+        cmdline="${argv[*]}"
+
+        if [[ "${cmdline}" =~ ${PROCESS_REGEX} ]]; then
+            printf '%s\n' "${pid}"
+        fi
+    done
+}
+
+terminate_game() {
+    local -a pids
+
+    mapfile -t pids < <(game_pids)
+
+    if [[ ${#pids[@]} -gt 0 ]]; then
+        log "Stopping game processes: ${pids[*]}"
+
+        kill -TERM "${pids[@]}" 2>/dev/null || true
+
+        sleep 3
+
+        mapfile -t pids < <(game_pids)
+
+        if [[ ${#pids[@]} -gt 0 ]]; then
+            log "Force stopping remaining processes: ${pids[*]}"
+            kill -KILL "${pids[@]}" 2>/dev/null || true
+        fi
+    fi
+}
+
+#
+# Important pour la suite :
+# si Sunshine arrête ce wrapper, on ferme également le jeu.
+#
+trap 'log "Wrapper received termination signal"; terminate_game; exit 143' \
+    TERM INT HUP
+
+log "Launching Steam AppID ${APPID}"
+log "Process regex: ${PROCESS_REGEX}"
+
+nohup steam -applaunch "${APPID}" \
+    >> "${LOG_FILE}" 2>&1 &
+
+#
+# Attendre que le vrai processus du jeu apparaisse.
+#
+start_time="${SECONDS}"
+
+while true; do
+    mapfile -t pids < <(game_pids)
+
+    if [[ ${#pids[@]} -gt 0 ]]; then
+        log "Game detected: ${pids[*]}"
+        break
+    fi
+
+    if (( SECONDS - start_time >= START_TIMEOUT )); then
+        log "ERROR: game did not appear within ${START_TIMEOUT}s"
+        exit 124
+    fi
+
+    sleep 1
+done
+
+#
+# Rester vivant aussi longtemps que le jeu.
+#
+missing_since=""
+
+while true; do
+    mapfile -t pids < <(game_pids)
+
+    if [[ ${#pids[@]} -gt 0 ]]; then
+        missing_since=""
+    else
+        if [[ -z "${missing_since}" ]]; then
+            missing_since="${SECONDS}"
+        fi
+
+        if (( SECONDS - missing_since >= EXIT_STABLE_TIME )); then
+            log "Game exited"
+            break
+        fi
+    fi
+
+    sleep 1
+done
+
+exit 0