Adds end-to-end Linux compatibility work for the dedicated server: new CI workflow (Ubuntu + Arch), line-ending/executable safeguards, and a local venv-first startup flow with split dependency files for server vs optional host GUI tooling. Improves runtime resilience with better bind error messages, stricter config validation, writable-state checks, cleaner socket/thread shutdown behavior, and SIGTERM-aware graceful stop handling for headless/systemd use. Updates deployment/startup docs and adds portability/runtime integration tests to lock in these behaviors.
149 lines
3.9 KiB
Bash
149 lines
3.9 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
cd "$(dirname "$0")"
|
|
|
|
PORT=7777
|
|
|
|
echo
|
|
echo "================================================================================"
|
|
echo " Commonwealth Online - Port ${PORT} in Use"
|
|
echo "================================================================================"
|
|
echo
|
|
echo "Port ${PORT} is currently in use by another process."
|
|
echo
|
|
echo "Options:"
|
|
echo " 1. Kill the process using port ${PORT} and restart server"
|
|
echo " 2. Use a different port (you will be prompted to enter one)"
|
|
echo " 3. Cancel and exit"
|
|
echo
|
|
|
|
read -r -p "Select option (1-3): " choice
|
|
|
|
find_pids_on_port() {
|
|
local port="$1"
|
|
local pids=""
|
|
|
|
if command -v lsof >/dev/null 2>&1; then
|
|
pids=$(lsof -tiTCP:"$port" -sTCP:LISTEN 2>/dev/null || true)
|
|
fi
|
|
|
|
if [[ -z "$pids" ]] && command -v fuser >/dev/null 2>&1; then
|
|
# fuser prints "7777/tcp: 1234 5678"
|
|
pids=$(fuser "${port}/tcp" 2>/dev/null | tr -s '[:space:]' '\n' | grep -E '^[0-9]+$' || true)
|
|
fi
|
|
|
|
if [[ -z "$pids" ]] && command -v ss >/dev/null 2>&1; then
|
|
pids=$(ss -lptn "sport = :${port}" 2>/dev/null | sed -n 's/.*pid=\([0-9]\+\).*/\1/p' | sort -u || true)
|
|
fi
|
|
|
|
echo "$pids"
|
|
}
|
|
|
|
# Prefer local venv, then python3, then python.
|
|
if [[ -x ".venv/bin/python" ]]; then
|
|
PYTHON=".venv/bin/python"
|
|
elif command -v python3 >/dev/null 2>&1; then
|
|
PYTHON=python3
|
|
elif command -v python >/dev/null 2>&1; then
|
|
PYTHON=python
|
|
else
|
|
echo "ERROR: Python is not installed or not in PATH."
|
|
exit 1
|
|
fi
|
|
|
|
case "$choice" in
|
|
1)
|
|
echo
|
|
echo "Finding process using port ${PORT}..."
|
|
pids=$(find_pids_on_port "$PORT")
|
|
|
|
if [[ -z "$pids" ]]; then
|
|
echo "Could not determine which process is using port ${PORT}."
|
|
echo "Try:"
|
|
echo " - Restarting your computer"
|
|
echo " - Running with elevated permissions"
|
|
echo " - Or choose option 2 to use a different port"
|
|
echo
|
|
echo "Manual tip: lsof -i :${PORT} or ss -lptn 'sport = :${PORT}'"
|
|
exit 1
|
|
fi
|
|
|
|
echo "Killing process(es): $pids"
|
|
# shellcheck disable=SC2086
|
|
if ! kill -9 $pids 2>/dev/null; then
|
|
echo "ERROR: Could not kill process. Try running this script with sudo."
|
|
exit 1
|
|
fi
|
|
echo "Process killed successfully."
|
|
echo
|
|
echo "Waiting for port to be released..."
|
|
sleep 2
|
|
echo
|
|
echo "Restarting server..."
|
|
exec bash ./start.sh
|
|
;;
|
|
2)
|
|
echo
|
|
read -r -p "Enter desired port (1024-65535, default is ${PORT}): " NEW_PORT
|
|
if [[ -z "${NEW_PORT}" ]]; then
|
|
NEW_PORT=$PORT
|
|
fi
|
|
|
|
if ! [[ "$NEW_PORT" =~ ^[0-9]+$ ]]; then
|
|
echo "ERROR: Port must be a number."
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "$NEW_PORT" -lt 1024 ]]; then
|
|
echo "ERROR: Port must be 1024 or higher."
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "$NEW_PORT" -gt 65535 ]]; then
|
|
echo "ERROR: Port must be 65535 or lower."
|
|
exit 1
|
|
fi
|
|
|
|
echo
|
|
echo "Updating commonwealth-server.json to use port ${NEW_PORT}..."
|
|
|
|
"$PYTHON" - <<PY
|
|
import json
|
|
from pathlib import Path
|
|
|
|
path = Path("commonwealth-server.json")
|
|
if path.exists():
|
|
with path.open("r", encoding="utf-8") as f:
|
|
cfg = json.load(f)
|
|
else:
|
|
cfg = {
|
|
"host": "0.0.0.0",
|
|
"port": ${NEW_PORT},
|
|
"server_name": "Commonwealth Online Server",
|
|
"max_players": 16,
|
|
"log_verbosity": "info",
|
|
}
|
|
|
|
cfg["port"] = ${NEW_PORT}
|
|
with path.open("w", encoding="utf-8") as f:
|
|
json.dump(cfg, f, indent=2)
|
|
f.write("\n")
|
|
PY
|
|
|
|
echo "Config updated. Restarting server on port ${NEW_PORT}..."
|
|
echo
|
|
exec bash ./start.sh
|
|
;;
|
|
3)
|
|
echo
|
|
echo "Cancelled."
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo
|
|
echo "Invalid option."
|
|
exit 1
|
|
;;
|
|
esac
|