#!/usr/bin/env bash set -euo pipefail MANAGER_PID_FILE="/var/run/openclaw/manager.pid" LOG_FILE="${OPENCLAW_GATEWAY_CTL_LOG_FILE:-/var/log/openclaw/gateway-ctl.log}" ts() { date -u +"%Y-%m-%dT%H:%M:%SZ"; } log_info() { local msg="[$(ts)] [INFO] openclaw-gateway-ctl: $*" printf '%s\n' "$msg" mkdir -p "$(dirname "$LOG_FILE")" printf '%s\n' "$msg" >> "$LOG_FILE" } log_error() { local msg="[$(ts)] [ERROR] openclaw-gateway-ctl: $*" printf '%s\n' "$msg" >&2 mkdir -p "$(dirname "$LOG_FILE")" printf '%s\n' "$msg" >> "$LOG_FILE" } get_manager_pid() { if [[ -f "$MANAGER_PID_FILE" ]]; then local pid pid=$(cat "$MANAGER_PID_FILE" 2>/dev/null | tr -d '[:space:]') if [[ -n "$pid" ]] && kill -0 "$pid" 2>/dev/null; then echo "$pid" return 0 fi fi return 1 } get_gateway_pid() { local port="${OPENCLAW_GATEWAY_PORT:-18789}" local pid pid=$(lsof -ti :"$port" -sTCP:LISTEN 2>/dev/null | head -1 || true) if [[ -n "$pid" ]] && kill -0 "$pid" 2>/dev/null; then local comm comm=$(ps -p "$pid" -o comm= 2>/dev/null || true) if [[ "$comm" == *"openclaw"* ]]; then echo "$pid" return 0 fi fi return 1 } do_status() { local manager_pid gateway_pid manager_pid=$(get_manager_pid 2>/dev/null) || true gateway_pid=$(get_gateway_pid 2>/dev/null) || true if [[ -n "$manager_pid" ]]; then log_info "manager is running (PID: $manager_pid)" else log_info "manager is not running" fi if [[ -n "$gateway_pid" ]]; then log_info "gateway is running (PID: $gateway_pid)" else log_info "gateway is not running" fi if [[ -n "$manager_pid" && -n "$gateway_pid" ]]; then return 0 else return 1 fi } do_start() { local manager_pid manager_pid=$(get_manager_pid) || true if [[ -z "$manager_pid" ]]; then log_error "manager is not running, cannot start gateway" return 1 fi log_info "Sending SIGUSR1 to manager (PID: $manager_pid) to start gateway..." kill -USR1 "$manager_pid" 2>/dev/null || true local waited=0 local max_wait=60 while [[ $waited -lt $max_wait ]]; do sleep 2 waited=$((waited + 2)) local gateway_pid gateway_pid=$(get_gateway_pid 2>/dev/null) || true if [[ -n "$gateway_pid" ]]; then log_info "Gateway started successfully (PID: $gateway_pid, waited ${waited}s)" return 0 fi done log_error "Gateway failed to start after ${max_wait}s" if [[ -f /var/log/openclaw/gateway.stderr.log ]]; then log_error "Last 5 lines from gateway stderr:" tail -5 /var/log/openclaw/gateway.stderr.log | while IFS= read -r line; do log_error " $line" done fi return 1 } do_stop() { local gateway_pid gateway_pid=$(get_gateway_pid) || true if [[ -z "$gateway_pid" ]]; then log_error "gateway is not running" return 1 fi log_info "Stopping gateway process (PID: $gateway_pid)..." kill -TERM "$gateway_pid" 2>/dev/null || true log_info "Waiting for gateway to stop (max 30s)..." local waited=0 while [[ $waited -lt 30 ]]; do if ! kill -0 "$gateway_pid" 2>/dev/null; then log_info "Gateway stopped gracefully" return 0 fi sleep 1 waited=$((waited + 1)) done log_error "Gateway did not stop gracefully, force killing..." kill -9 "$gateway_pid" 2>/dev/null || true log_info "Gateway killed" } do_restart() { local manager_pid gateway_pid manager_pid=$(get_manager_pid) || true gateway_pid=$(get_gateway_pid) || true if [[ -z "$manager_pid" ]]; then log_error "manager is not running, cannot restart gateway" return 1 fi if [[ -n "$gateway_pid" ]]; then log_info "Stopping gateway process (PID: $gateway_pid)..." kill -TERM "$gateway_pid" 2>/dev/null || true sleep 1 fi log_info "Sending SIGUSR1 to manager (PID: $manager_pid) to restart gateway..." kill -USR1 "$manager_pid" 2>/dev/null || true local waited=0 local max_wait=60 while [[ $waited -lt $max_wait ]]; do sleep 2 waited=$((waited + 2)) gateway_pid=$(get_gateway_pid 2>/dev/null) || true if [[ -n "$gateway_pid" ]]; then log_info "Gateway restarted successfully (PID: $gateway_pid, waited ${waited}s)" return 0 fi done log_error "Gateway failed to restart after ${max_wait}s" if [[ -f /var/log/openclaw/gateway.stderr.log ]]; then log_error "Last 5 lines from gateway stderr:" tail -5 /var/log/openclaw/gateway.stderr.log | while IFS= read -r line; do log_error " $line" done fi return 1 } do_reload() { local gateway_pid gateway_pid=$(get_gateway_pid) || true if [[ -z "$gateway_pid" ]]; then log_error "gateway is not running" return 1 fi log_info "Sending SIGHUP to gateway (PID: $gateway_pid)..." kill -HUP "$gateway_pid" 2>/dev/null || true } ACTION="${1:-}" case "$ACTION" in start|START) do_start ;; stop|STOP) do_stop ;; restart|RESTART) do_restart ;; reload|RELOAD) do_reload ;; status|STATUS|"") do_status ;; *) echo "Usage: openclaw-gateway-ctl {start|stop|restart|reload|status}" echo "" echo " start - Start gateway (via manager)" echo " stop - Stop only gateway process (manager keeps running)" echo " restart - Stop gateway then start via manager (no bootstrap)" echo " reload - Send SIGHUP to gateway for config reload" echo " status - Show running status" exit 1 ;; esac