#!/usr/bin/env bash # Copyright 2024-2026 The DragonX Developers # Released under GPLv3 # # Monitors lightwalletd and restarts it automatically if it crashes. # Usage: ./monitor_lwd.sh & # or: nohup ./monitor_lwd.sh >> /tmp/lwd-monitor.log 2>&1 & set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" LWD_BIN="$SCRIPT_DIR/lightwalletd" LWD_ARGS="-bind-addr lite.dragonx.is:9069 -conf-file $HOME/.hush/DRAGONX/DRAGONX.conf -no-tls" LOGFILE="$SCRIPT_DIR/lwd-monitor.log" PIDFILE="/tmp/lwd-monitor.pid" RESTART_DELAY=5 # seconds to wait before restarting after a crash MAX_RAPID_RESTARTS=5 # max restarts within the rapid window before backing off RAPID_WINDOW=120 # seconds — if this many restarts happen within this window, back off BACKOFF_DELAY=60 # seconds to wait when backing off # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' log() { echo -e "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOGFILE" } cleanup() { log "${YELLOW}Monitor shutting down...${NC}" if [[ -n "${LWD_PID:-}" ]] && kill -0 "$LWD_PID" 2>/dev/null; then log "Stopping lightwalletd (PID $LWD_PID)..." kill "$LWD_PID" 2>/dev/null || true wait "$LWD_PID" 2>/dev/null || true fi rm -f "$PIDFILE" log "Monitor stopped." exit 0 } trap cleanup SIGINT SIGTERM # Prevent duplicate monitors if [[ -f "$PIDFILE" ]]; then OLD_PID=$(cat "$PIDFILE") if kill -0 "$OLD_PID" 2>/dev/null; then echo "Monitor already running (PID $OLD_PID). Exiting." exit 1 fi rm -f "$PIDFILE" fi echo $$ > "$PIDFILE" # Check binary exists if [[ ! -x "$LWD_BIN" ]]; then log "${RED}ERROR: lightwalletd binary not found at $LWD_BIN${NC}" log "Build it first with: make build" rm -f "$PIDFILE" exit 1 fi # Check conf file exists CONF_FILE="$HOME/.hush/DRAGONX/DRAGONX.conf" if [[ ! -f "$CONF_FILE" ]]; then log "${RED}ERROR: DRAGONX.conf not found at $CONF_FILE${NC}" rm -f "$PIDFILE" exit 1 fi log "${GREEN}DragonX lightwalletd monitor started (PID $$)${NC}" log "Binary: $LWD_BIN" log "Args: $LWD_ARGS" restart_times=() LWD_PID="" while true; do # Start lightwalletd log "${GREEN}Starting lightwalletd...${NC}" $LWD_BIN $LWD_ARGS >> "$LOGFILE" 2>&1 & LWD_PID=$! log "lightwalletd started with PID $LWD_PID" # Wait for it to exit wait "$LWD_PID" || true EXIT_CODE=$? LWD_PID="" if [[ $EXIT_CODE -eq 0 ]]; then log "${YELLOW}lightwalletd exited cleanly (code 0). Not restarting.${NC}" break fi log "${RED}lightwalletd crashed with exit code $EXIT_CODE${NC}" # Track restart frequency for backoff NOW=$(date +%s) restart_times+=("$NOW") # Trim old entries outside the rapid window CUTOFF=$((NOW - RAPID_WINDOW)) filtered=() for t in "${restart_times[@]}"; do if (( t >= CUTOFF )); then filtered+=("$t") fi done restart_times=("${filtered[@]}") if (( ${#restart_times[@]} >= MAX_RAPID_RESTARTS )); then log "${YELLOW}Too many restarts (${#restart_times[@]} in ${RAPID_WINDOW}s). Backing off for ${BACKOFF_DELAY}s...${NC}" sleep "$BACKOFF_DELAY" restart_times=() else log "Restarting in ${RESTART_DELAY}s..." sleep "$RESTART_DELAY" fi done rm -f "$PIDFILE" log "Monitor exiting."