stop.sh
1 #!/usr/bin/env bash 2 # 3 # stop.sh - Stop the ADnet development network 4 # 5 # Usage: ./stop.sh [OPTIONS] 6 # 7 # Options: 8 # -d, --data-dir DIR Data directory (default: .devnet) 9 # --save-state Save state before stopping 10 # -f, --force Force kill processes 11 # -v, --verbose Enable verbose output 12 # -h, --help Show this help message 13 14 set -euo pipefail 15 16 # Script directory 17 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 18 DEVNET_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" 19 20 # Default configuration 21 DATA_DIR="${DEVNET_DIR}/.devnet" 22 SAVE_STATE=false 23 FORCE=false 24 VERBOSE=false 25 26 # Colors for output 27 RED='\033[0;31m' 28 GREEN='\033[0;32m' 29 YELLOW='\033[1;33m' 30 BLUE='\033[0;34m' 31 NC='\033[0m' # No Color 32 33 # Logging functions 34 log_info() { 35 echo -e "${GREEN}[INFO]${NC} $1" 36 } 37 38 log_warn() { 39 echo -e "${YELLOW}[WARN]${NC} $1" 40 } 41 42 log_error() { 43 echo -e "${RED}[ERROR]${NC} $1" >&2 44 } 45 46 log_debug() { 47 if [ "$VERBOSE" = true ]; then 48 echo -e "${BLUE}[DEBUG]${NC} $1" 49 fi 50 } 51 52 # Show usage 53 usage() { 54 cat <<EOF 55 Usage: $(basename "$0") [OPTIONS] 56 57 Stop the ADnet development network. 58 59 Options: 60 -d, --data-dir DIR Data directory (default: .devnet) 61 --save-state Save state before stopping (placeholder) 62 -f, --force Force kill processes (SIGKILL) 63 -v, --verbose Enable verbose output 64 -h, --help Show this help message 65 66 Examples: 67 $(basename "$0") # Graceful stop 68 $(basename "$0") -f # Force stop 69 $(basename "$0") --save-state # Save state before stopping 70 71 EOF 72 exit 0 73 } 74 75 # Parse command line arguments 76 parse_args() { 77 while [[ $# -gt 0 ]]; do 78 case $1 in 79 -d|--data-dir) 80 DATA_DIR="$2" 81 shift 2 82 ;; 83 --save-state) 84 SAVE_STATE=true 85 shift 86 ;; 87 -f|--force) 88 FORCE=true 89 shift 90 ;; 91 -v|--verbose) 92 VERBOSE=true 93 shift 94 ;; 95 -h|--help) 96 usage 97 ;; 98 *) 99 log_error "Unknown option: $1" 100 usage 101 ;; 102 esac 103 done 104 } 105 106 # Save state (placeholder) 107 save_state() { 108 if [ "$SAVE_STATE" = true ]; then 109 log_info "Saving state... (placeholder)" 110 # Future: Implement state snapshot 111 fi 112 } 113 114 # Stop a process by PID file 115 stop_process() { 116 local pid_file=$1 117 local name=$2 118 119 if [ ! -f "$pid_file" ]; then 120 log_debug "No PID file for $name" 121 return 0 122 fi 123 124 local pid 125 pid=$(cat "$pid_file" 2>/dev/null || echo "") 126 127 if [ -z "$pid" ]; then 128 log_debug "Empty PID file for $name" 129 rm -f "$pid_file" 130 return 0 131 fi 132 133 if ! kill -0 "$pid" 2>/dev/null; then 134 log_debug "$name (PID $pid) not running" 135 rm -f "$pid_file" 136 return 0 137 fi 138 139 log_info "Stopping $name (PID $pid)..." 140 141 if [ "$FORCE" = true ]; then 142 kill -9 "$pid" 2>/dev/null || true 143 else 144 # Graceful shutdown 145 kill -TERM "$pid" 2>/dev/null || true 146 147 # Wait for process to stop 148 local wait_count=0 149 while kill -0 "$pid" 2>/dev/null && [ $wait_count -lt 30 ]; do 150 sleep 0.5 151 wait_count=$((wait_count + 1)) 152 done 153 154 # Force kill if still running 155 if kill -0 "$pid" 2>/dev/null; then 156 log_warn "$name did not stop gracefully, forcing..." 157 kill -9 "$pid" 2>/dev/null || true 158 fi 159 fi 160 161 rm -f "$pid_file" 162 log_debug "$name stopped" 163 } 164 165 # Stop all validators 166 stop_validators() { 167 local pids_dir="${DATA_DIR}/pids" 168 169 if [ ! -d "$pids_dir" ]; then 170 log_info "No PID directory found. Devnet may not be running." 171 return 0 172 fi 173 174 # Find all validator PID files 175 local stopped=0 176 for pid_file in "$pids_dir"/validator-*.pid; do 177 if [ -f "$pid_file" ]; then 178 local name 179 name=$(basename "$pid_file" .pid) 180 stop_process "$pid_file" "$name" 181 stopped=$((stopped + 1)) 182 fi 183 done 184 185 if [ $stopped -eq 0 ]; then 186 log_info "No validators were running" 187 else 188 log_info "Stopped $stopped validator(s)" 189 fi 190 } 191 192 # Verify all processes stopped 193 verify_stopped() { 194 local pids_dir="${DATA_DIR}/pids" 195 196 if [ ! -d "$pids_dir" ]; then 197 return 0 198 fi 199 200 local running=0 201 for pid_file in "$pids_dir"/*.pid; do 202 if [ -f "$pid_file" ]; then 203 local pid 204 pid=$(cat "$pid_file" 2>/dev/null || echo "") 205 if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then 206 running=$((running + 1)) 207 log_warn "Process $pid is still running" 208 fi 209 fi 210 done 211 212 if [ $running -gt 0 ]; then 213 log_error "$running process(es) still running" 214 return 1 215 fi 216 217 log_info "All processes stopped successfully" 218 } 219 220 # Main function 221 main() { 222 parse_args "$@" 223 224 echo "" 225 echo "Stopping ADnet Devnet..." 226 echo "" 227 228 # Save state if requested 229 save_state 230 231 # Stop all validators 232 stop_validators 233 234 # Verify stopped 235 verify_stopped 236 237 echo "" 238 echo "==========================================" 239 echo " ADnet Devnet Stopped" 240 echo "==========================================" 241 echo "" 242 } 243 244 # Run main 245 main "$@"