mirror of
https://github.com/Ayymoss/Plutainer
synced 2026-08-24 14:32:06 -04:00
Log Watcher
This commit is contained in:
parent
bd03dcf042
commit
e749a787a4
6 changed files with 85 additions and 4 deletions
|
|
@ -41,11 +41,13 @@ Everything runs as the `plutainer` user from `/home/plutainer/.plutainer`.
|
|||
|
||||
5. **`game-config.sh`** — Shared shell library sourced by all other scripts. Single source of truth for game detection, port defaults, config path resolution, and RCON password extraction.
|
||||
|
||||
6. **`healthcheck.sh`** — Sources `game-config.sh`, then uses `pyquake3.py` to send an RCON `status` command. Can be disabled with `PLUTO_HEALTHCHECK=true`, `IW4X_HEALTHCHECK=true`, or `ALTER_HEALTHCHECK=true`.
|
||||
6. **`log-watcher.sh`** — Background poller started by each entrypoint before `exec wine`. Maintains stable symlinks at `/home/plutainer/app/logs/<name>` pointing at the active game log (e.g. `games_mp.log`, `games_zm.log`). Uses container boot time as a mtime cutoff so stale logs from prior sessions and abandoned mod dirs are ignored. Disable with `PLUTAINER_LOG_SYMLINKS=false`; poll interval via `PLUTAINER_LOG_POLL_INTERVAL` (default 2s).
|
||||
|
||||
7. **`rcon-cli`** — Python script providing interactive and one-shot RCON access via `docker exec`. Calls `game-config.sh` to resolve port/credentials. Supports Plutonium, IW4x, and Alterware.
|
||||
7. **`healthcheck.sh`** — Sources `game-config.sh`, then uses `pyquake3.py` to send an RCON `status` command. Can be disabled with `PLUTO_HEALTHCHECK=true`, `IW4X_HEALTHCHECK=true`, or `ALTER_HEALTHCHECK=true`.
|
||||
|
||||
7. **`pyquake3.py`** — Python 3 Quake 3 protocol library (UDP). Used by the health check and `rcon-cli` for RCON queries.
|
||||
8. **`rcon-cli`** — Python script providing interactive and one-shot RCON access via `docker exec`. Calls `game-config.sh` to resolve port/credentials. Supports Plutonium, IW4x, and Alterware.
|
||||
|
||||
9. **`pyquake3.py`** — Python 3 Quake 3 protocol library (UDP). Used by the health check and `rcon-cli` for RCON queries.
|
||||
|
||||
## Game-Specific Behavior
|
||||
|
||||
|
|
@ -60,4 +62,5 @@ For Plutonium, `BASE_GAME` is derived by stripping the last two chars from `PLUT
|
|||
|
||||
- `/home/plutainer/gamefiles` — bind-mounted read-only game files from host
|
||||
- `/home/plutainer/app` — persistent volume (gamefiles symlinks, plutonium data, configs, logs)
|
||||
- `/home/plutainer/app/logs` — stable symlinks to active game logs, maintained by `log-watcher.sh`. Host-side IW4MAdmin should bind-mount this dir and read logs from there instead of reaching into nested mod/storage paths.
|
||||
- `/home/plutainer/.plutainer` — working directory containing scripts, updaters, and pyquake3
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ RUN IW4X_URL=$(wget -qO- https://api.github.com/repos/iw4x/launcher/releases/lat
|
|||
|
||||
# Copy all scripts and the python module into the image
|
||||
COPY --chown=plutainer:plutainer scripts/ .
|
||||
RUN chmod +x entrypoint.sh healthcheck.sh plutoentry.sh iw4xentry.sh alterentry.sh rcon-cli game-config.sh
|
||||
RUN chmod +x entrypoint.sh healthcheck.sh plutoentry.sh iw4xentry.sh alterentry.sh log-watcher.sh rcon-cli game-config.sh
|
||||
|
||||
# Add rcon-cli to PATH so it can be invoked without a full path via docker exec
|
||||
USER root
|
||||
|
|
|
|||
|
|
@ -109,6 +109,8 @@ rm -f /tmp/.X99-lock
|
|||
Xvfb :99 -screen 0 320x240x24 &
|
||||
sleep 1
|
||||
|
||||
/home/plutainer/.plutainer/log-watcher.sh &
|
||||
|
||||
echo "Starting T7x Server: ${ALTER_SERVER_NAME}"
|
||||
echo "EXECUTING: wine t7x.exe ${CMD_ARGS[@]}"
|
||||
exec wine t7x.exe "${CMD_ARGS[@]}"
|
||||
|
|
|
|||
|
|
@ -92,6 +92,8 @@ fi
|
|||
CMD_ARGS+=(+map_rotate)
|
||||
|
||||
# --- Step 5: Launch the iw4x Server ---
|
||||
/home/plutainer/.plutainer/log-watcher.sh &
|
||||
|
||||
echo "Starting ${IW4X_GAME} Server: ${IW4X_SERVER_NAME}"
|
||||
echo "EXECUTING: wine iw4x.exe ${CMD_ARGS[@]}"
|
||||
exec wine iw4x.exe "${CMD_ARGS[@]}"
|
||||
|
|
|
|||
72
scripts/log-watcher.sh
Normal file
72
scripts/log-watcher.sh
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Maintains stable symlinks at /home/plutainer/app/logs/<name> pointing at the
|
||||
# game log currently being written. Game logs move around per game/mod (e.g.
|
||||
# plutonium/storage/t5/mods/<mod>/logs/games_zm.log), which makes IW4MAdmin
|
||||
# configuration brittle. This watcher surfaces them in one predictable dir.
|
||||
#
|
||||
# Strategy:
|
||||
# - Record container boot time.
|
||||
# - Poll app/ for files matching known log names.
|
||||
# - The active log is the one with mtime >= boot time (stale logs from prior
|
||||
# sessions keep their old mtime and are ignored). Ties broken by newest.
|
||||
# - Update symlink only when target changes (idempotent).
|
||||
# - Create empty stub files at startup so host-side IW4MAdmin never sees a
|
||||
# dangling symlink during the window before the first write event.
|
||||
#
|
||||
|
||||
APP_DIR=/home/plutainer/app
|
||||
STABLE_DIR="$APP_DIR/logs"
|
||||
POLL_INTERVAL="${PLUTAINER_LOG_POLL_INTERVAL:-2}"
|
||||
LOG_NAMES=(games_mp.log games_zm.log console_mp.log console_zm.log)
|
||||
|
||||
if [[ "${PLUTAINER_LOG_SYMLINKS}" == "false" ]]; then
|
||||
echo "[log-watcher] disabled via PLUTAINER_LOG_SYMLINKS=false"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mkdir -p "$STABLE_DIR"
|
||||
|
||||
for name in "${LOG_NAMES[@]}"; do
|
||||
target="$STABLE_DIR/$name"
|
||||
if [[ -L "$target" ]]; then
|
||||
# Leave existing symlinks from prior run in place until a fresh target is
|
||||
# identified. Preserves continuity for IW4MAdmin across container restarts
|
||||
# where the old log path is still valid.
|
||||
:
|
||||
elif [[ ! -e "$target" ]]; then
|
||||
touch "$target"
|
||||
fi
|
||||
done
|
||||
|
||||
BOOT_TS=$(date +%s)
|
||||
|
||||
declare -A CURRENT_TARGET
|
||||
|
||||
echo "[log-watcher] started; boot_ts=$BOOT_TS stable_dir=$STABLE_DIR"
|
||||
|
||||
while true; do
|
||||
for name in "${LOG_NAMES[@]}"; do
|
||||
newest_path=""
|
||||
newest_mtime=0
|
||||
|
||||
while IFS= read -r -d '' path; do
|
||||
mtime=$(stat -c %Y "$path" 2>/dev/null) || continue
|
||||
(( mtime < BOOT_TS )) && continue
|
||||
if (( mtime > newest_mtime )); then
|
||||
newest_mtime=$mtime
|
||||
newest_path=$path
|
||||
fi
|
||||
done < <(find "$APP_DIR" -path "$STABLE_DIR" -prune -o -type f -name "$name" -print0 2>/dev/null)
|
||||
|
||||
if [[ -n "$newest_path" && "$newest_path" != "${CURRENT_TARGET[$name]:-}" ]]; then
|
||||
link="$STABLE_DIR/$name"
|
||||
rm -f "$link"
|
||||
ln -s "$newest_path" "$link"
|
||||
CURRENT_TARGET[$name]=$newest_path
|
||||
echo "[log-watcher] $name -> $newest_path"
|
||||
fi
|
||||
done
|
||||
|
||||
sleep "$POLL_INTERVAL"
|
||||
done
|
||||
|
|
@ -132,6 +132,8 @@ else
|
|||
fi
|
||||
|
||||
# --- Step 5: Launch the Plutonium Server ---
|
||||
/home/plutainer/.plutainer/log-watcher.sh &
|
||||
|
||||
echo "Starting Plutonium ${PLUTO_GAME} Server: ${PLUTO_SERVER_NAME}"
|
||||
echo "EXECUTING: wine bin/plutonium-bootstrapper-win32.exe ${CMD_ARGS[@]}"
|
||||
exec wine bin/plutonium-bootstrapper-win32.exe "${CMD_ARGS[@]}"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue