From 19569732515c06a5597c534d1410b1d8cad861ca Mon Sep 17 00:00:00 2001 From: webdevpraveen Date: Wed, 18 Mar 2026 23:03:52 +0530 Subject: [PATCH] fix(install): check ports 8080 and 18789 are free before starting gateway Fixes #51 install.sh starts the OpenShell gateway on port 8080 and the OpenClaw dashboard on port 18789 without checking whether those ports are already in use. Users with existing Docker containers, web servers, or other services on those ports get a cryptic startup failure: Error: listen tcp 0.0.0.0:8080: bind: address already in use This change adds a check_required_ports() preflight function that runs before any gateway or sandbox setup: - Detects conflicts using ss (iproute2) with netstat fallback - Prints a clear, named error identifying the conflicting port - Suggests NEMOCLAW_GATEWAY_PORT / NEMOCLAW_DASHBOARD_PORT env vars so users can override without stopping existing services - Degrades gracefully when neither ss nor netstat is available Signed-off-by: webdevpraveen --- install.sh | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/install.sh b/install.sh index 9eeb429aa11..32a6876886d 100755 --- a/install.sh +++ b/install.sh @@ -59,6 +59,47 @@ version_major() { printf '%s\n' "${1#v}" | cut -d. -f1 } +# ── Port availability preflight ────────────────────────────────────── +# NemoClaw requires two ports to be free before setup starts: +# NEMOCLAW_GATEWAY_PORT (default 8080) – OpenShell gateway +# NEMOCLAW_DASHBOARD_PORT (default 18789) – OpenClaw dashboard +# Override via env var to avoid killing existing services. +NEMOCLAW_GATEWAY_PORT="${NEMOCLAW_GATEWAY_PORT:-8080}" +NEMOCLAW_DASHBOARD_PORT="${NEMOCLAW_DASHBOARD_PORT:-18789}" + +_port_in_use() { + local p="$1" + if command -v ss &>/dev/null; then + ss -tlnH 2>/dev/null | awk '{print $4}' | grep -q ":${p}$" + return $? + elif command -v netstat &>/dev/null; then + netstat -tlnH 2>/dev/null | awk '{print $4}' | grep -q ":${p}$" + return $? + fi + return 1 +} + +check_required_ports() { + local failed=0 + for spec in "${NEMOCLAW_GATEWAY_PORT}:gateway" "${NEMOCLAW_DASHBOARD_PORT}:dashboard"; do + local port="${spec%%:*}" label="${spec##*:}" + if _port_in_use "$port"; then + echo "[ERROR] Port $port ($label) is already in use." >&2 + echo "[ERROR] Find the process : ss -tlnp | grep :$port" >&2 + echo "[ERROR] Or override : export NEMOCLAW_${label^^}_PORT=" >&2 + failed=1 + fi + done + if [ "$failed" -eq 1 ]; then + echo "" >&2 + echo "[ERROR] Free the ports above (or set override env vars), then re-run." >&2 + exit 1 + fi + echo "[INFO] Ports ${NEMOCLAW_GATEWAY_PORT} (gateway) and ${NEMOCLAW_DASHBOARD_PORT} (dashboard) are free." +} +# ───────────────────────────────────────────────────────────────────── + + ensure_supported_runtime() { command_exists node || error "${RUNTIME_REQUIREMENT_MSG} Node.js was not found on PATH." command_exists npm || error "${RUNTIME_REQUIREMENT_MSG} npm was not found on PATH." @@ -98,6 +139,7 @@ install_nodejs() { || { rm -f "$nvm_tmp"; error "Failed to download nvm installer"; } local actual_hash if command_exists sha256sum; then +check_required_ports actual_hash="$(sha256sum "$nvm_tmp" | awk '{print $1}')" elif command_exists shasum; then actual_hash="$(shasum -a 256 "$nvm_tmp" | awk '{print $1}')"