#!/usr/bin/env bash # # SearXNG Reset Script (3-instance cluster) # ========================================== # Clears CAPTCHA/rate-limit state and restarts SearXNG instances. # # Usage: # ./searxng-reset.sh # Full reset (flush all + restart all) # ./searxng-reset.sh --status # Show engine error counts # ./searxng-reset.sh --check # Quick health check # ./searxng-reset.sh --one 2 # Reset only instance 2 # set -euo pipefail INSTANCES=(1 2 3) LB_CONTAINER="didiAI-web-searxng" SEARXNG_URL="http://localhost:55100" RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' check_health() { echo "=== Health Check ===" echo "" # LB local lb_status lb_status=$(curl -s --max-time 5 "${SEARXNG_URL}/healthz" 2>/dev/null) || true if [[ "$lb_status" == "OK" ]]; then echo -e "Load balancer (55100): ${GREEN}UP${NC}" else echo -e "Load balancer (55100): ${RED}DOWN${NC}" fi # Individual instances for i in "${INSTANCES[@]}"; do local container="didiAI-web-searxng-${i}" local status status=$(docker inspect --format '{{.State.Health.Status}}' "$container" 2>/dev/null) || status="not found" if [[ "$status" == "healthy" ]]; then echo -e " Instance ${i}: ${GREEN}${status}${NC}" else echo -e " Instance ${i}: ${RED}${status}${NC}" fi done # Test search echo "" local results results=$(curl -s --max-time 10 "${SEARXNG_URL}/search?q=test&format=json" 2>/dev/null \ | python3 -c "import sys,json; d=json.load(sys.stdin); print(len(d.get('results',[])))" 2>/dev/null) || results=0 if [[ "$results" -gt 0 ]]; then echo -e "Search test: ${GREEN}OK ($results results)${NC}" else echo -e "Search test: ${RED}FAILED (0 results)${NC}" fi } show_status() { echo "=== Engine Errors (all instances) ===" echo "" for i in "${INSTANCES[@]}"; do local container="didiAI-web-searxng-${i}" echo -e "${YELLOW}Instance ${i} ($container):${NC}" local captcha_count captcha_count=$(docker logs "$container" 2>&1 | grep -ci 'CAPTCHA' 2>/dev/null) || captcha_count=0 local toomany_count toomany_count=$(docker logs "$container" 2>&1 | grep -ci 'TooManyRequests' 2>/dev/null) || toomany_count=0 if [[ $captcha_count -gt 0 || $toomany_count -gt 0 ]]; then echo " CAPTCHA: $captcha_count | TooManyRequests: $toomany_count" docker logs "$container" 2>&1 \ | grep -iE 'CAPTCHA|TooMany' \ | grep -oP 'engines\.\K[^:]+' \ | sort | uniq -c | sort -rn \ | sed 's/^/ /' || true else echo -e " ${GREEN}Clean (no errors)${NC}" fi echo "" done } reset_instance() { local i=$1 local container="didiAI-web-searxng-${i}" local redis="didiAI-web-searxng-redis-${i}" echo -n " [${i}] Flush Redis... " if docker exec "$redis" valkey-cli FLUSHALL > /dev/null 2>&1; then echo -e "${GREEN}OK${NC}" else echo -e "${YELLOW}WARN${NC}" fi echo -n " [${i}] Restart SearXNG... " docker restart "$container" > /dev/null 2>&1 echo -e "${GREEN}OK${NC}" } do_reset() { local targets=("${@}") if [[ ${#targets[@]} -eq 0 ]]; then targets=("${INSTANCES[@]}") fi echo "=== SearXNG Reset ===" echo "Resetting instances: ${targets[*]}" echo "" for i in "${targets[@]}"; do reset_instance "$i" done # Wait for health echo "" echo -n "Waiting for startup... " local attempts=0 while [[ $attempts -lt 15 ]]; do sleep 2 local healthy=0 for i in "${targets[@]}"; do local status status=$(docker inspect --format '{{.State.Health.Status}}' "didiAI-web-searxng-${i}" 2>/dev/null) || status="none" [[ "$status" == "healthy" ]] && healthy=$((healthy + 1)) done if [[ $healthy -eq ${#targets[@]} ]]; then echo -e "${GREEN}All ${healthy} instances UP${NC}" echo "" check_health return 0 fi attempts=$((attempts + 1)) done echo -e "${YELLOW}Some instances still starting (check with --check)${NC}" } # Parse arguments case "${1:-}" in --status|-s) show_status ;; --check|-c) check_health ;; --one|-o) [[ -z "${2:-}" ]] && echo "Usage: $0 --one <1|2|3>" && exit 1 do_reset "$2" ;; --help|-h) sed -n '2,12p' "$0" | sed 's/^# //' | sed 's/^#//' ;; *) do_reset ;; esac