manage_services.sh 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #!/bin/bash
  2. #ident "@(#)$Format:LocalFoodAI_lanfr144:manage_services.sh:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$"
  3. # ==============================================================================
  4. # File: manage_services.sh
  5. # Purpose: Comprehensive Service Manager for Local Food AI development.
  6. # Allows operators and developers to cleanly start, stop, restart,
  7. # and inspect all project elements in sequential order of dependencies
  8. # without triggering online data ingestion pipelines.
  9. # ==============================================================================
  10. # Exit immediately if a command exits with a non-zero status (except when checked)
  11. set -e
  12. # Sequence priority rules:
  13. # STARTUP: 1. MySQL -> 2. Ollama & SearXNG -> 3. Streamlit App & Nginx Proxy -> 4. Zabbix & Airflow
  14. # SHUTDOWN: 1. Zabbix & Airflow -> 2. Nginx & App -> 3. SearXNG & Ollama -> 4. MySQL
  15. COMPOSE_FILE="docker-compose.yml"
  16. # Auto-detect WSL context and use port-shifted docker-compose-wsl.yml
  17. if [ -f "docker-compose-wsl.yml" ] && (grep -qi "microsoft" /proc/sys/kernel/osrelease 2>/dev/null || grep -qi "wsl" /proc/sys/kernel/osrelease 2>/dev/null); then
  18. COMPOSE_FILE="docker-compose-wsl.yml"
  19. fi
  20. # Colors for output logging
  21. GREEN='\033[0;32m'
  22. BLUE='\033[0;34m'
  23. YELLOW='\033[1;33m'
  24. RED='\033[0;31m'
  25. NC='\033[0m' # No Color
  26. log_info() {
  27. echo -e "${BLUE}[INFO] $(date '+%Y-%m-%d %H:%M:%S') - $1${NC}"
  28. }
  29. log_success() {
  30. echo -e "${GREEN}[SUCCESS] $(date '+%Y-%m-%d %H:%M:%S') - $1${NC}"
  31. }
  32. log_warn() {
  33. echo -e "${YELLOW}[WARNING] $(date '+%Y-%m-%d %H:%M:%S') - $1${NC}"
  34. }
  35. log_error() {
  36. echo -e "${RED}[ERROR] $(date '+%Y-%m-%d %H:%M:%S') - $1${NC}"
  37. }
  38. # Verify Docker Compose file exists
  39. if [ ! -f "$COMPOSE_FILE" ]; then
  40. log_error "Docker Compose file ($COMPOSE_FILE) not found in the current directory."
  41. exit 1
  42. fi
  43. start_services() {
  44. log_info "Initiating sequential startup sequence for development..."
  45. # Step 1: Start MySQL Database
  46. log_info "Step 1/4: Starting MySQL Database Container..."
  47. docker compose -f "$COMPOSE_FILE" up -d mysql
  48. # Wait for MySQL to become fully ready and accept connections
  49. log_info "Waiting for MySQL database socket to be available..."
  50. DB_ROOT_PASS="your_db_password_here"
  51. if [ -f "./.env" ]; then
  52. ENV_PASS=$(grep '^[ \t]*MYSQL_ROOT_PASSWORD[ \t]*=' .env | sed 's/^.*=//' | tr -d '\r\n ')
  53. if [ ! -z "$ENV_PASS" ]; then
  54. DB_ROOT_PASS="$ENV_PASS"
  55. fi
  56. fi
  57. until docker compose -f "$COMPOSE_FILE" exec mysql mysqladmin ping -h"localhost" -u"root" -p"$DB_ROOT_PASS" --silent; do
  58. sleep 2
  59. echo -n "."
  60. done
  61. echo ""
  62. log_success "MySQL is online and healthy."
  63. # Step 2: Start local AI Engine (Ollama) and Anonymous Search (SearXNG)
  64. log_info "Step 2/4: Starting Ollama and SearXNG microservices..."
  65. docker compose -f "$COMPOSE_FILE" up -d ollama searxng
  66. # Wait briefly for Ollama daemon bind
  67. sleep 3
  68. log_success "AI and Search infrastructure successfully online."
  69. # Step 3: Start Core Streamlit Application UI and Nginx Gateway Proxy
  70. log_info "Step 3/4: Starting Streamlit UI and Nginx Proxy Gateway..."
  71. docker compose -f "$COMPOSE_FILE" up -d app nginx
  72. log_success "Frontend and Proxy elements online."
  73. # Step 4: Start DevOps Orchestrator Stack (Zabbix Monitoring, Zabbix Agent, Airflow)
  74. log_info "Step 4/4: Deploying Zabbix Monitoring suite and Airflow Supervisors..."
  75. # Note: Airflow scheduler/webserver are started for pipeline supervision
  76. docker compose -f "$COMPOSE_FILE" up -d zabbix-server zabbix-web zabbix-agent
  77. # Check if Airflow service elements exist in compose file before starting
  78. if grep -q "airflow-webserver" "$COMPOSE_FILE"; then
  79. docker compose -f "$COMPOSE_FILE" up -d airflow-webserver airflow-scheduler || log_warn "Airflow containers not defined or failed to start."
  80. fi
  81. log_success "All Local Food AI development services started successfully!"
  82. }
  83. stop_services() {
  84. log_info "Initiating sequential graceful shutdown sequence..."
  85. # Step 1: Stop Monitoring and Supervisor Stack
  86. log_info "Step 1/4: Stopping Zabbix suite and Airflow Supervisors..."
  87. docker compose -f "$COMPOSE_FILE" stop zabbix-agent zabbix-web zabbix-server
  88. if grep -q "airflow-webserver" "$COMPOSE_FILE"; then
  89. docker compose -f "$COMPOSE_FILE" stop airflow-scheduler airflow-webserver || true
  90. fi
  91. log_success "DevOps monitoring stack shut down."
  92. # Step 2: Stop Streamlit Application and Secure Proxy Gateway
  93. log_info "Step 2/4: Shutting down Nginx and App frontend..."
  94. docker compose -f "$COMPOSE_FILE" stop nginx app
  95. log_success "Application frontend shut down."
  96. # Step 3: Stop AI Ollama Inference Engine and SearXNG Search Gateway
  97. log_info "Step 3/4: Stopping SearXNG and Ollama AI Engine..."
  98. docker compose -f "$COMPOSE_FILE" stop searxng ollama
  99. log_success "AI services shut down."
  100. # Step 4: Stop Core MySQL Database Container gracefully (prevent table corruption)
  101. log_info "Step 4/4: Stopping MySQL database..."
  102. docker compose -f "$COMPOSE_FILE" stop mysql
  103. log_success "Database node cleanly shut down."
  104. log_success "All Local Food AI services stopped gracefully!"
  105. }
  106. check_status() {
  107. log_info "Inspecting status of stack containers..."
  108. docker compose -f "$COMPOSE_FILE" ps
  109. log_info "Active network sockets check:"
  110. echo "---------------------------------------------------------"
  111. echo "Port | Target Service | Status"
  112. echo "---------------------------------------------------------"
  113. # Check MySQL on 3307
  114. if nc -z localhost 3307 2>/dev/null; then
  115. echo -e "3307 | MySQL Database Node | ${GREEN}ONLINE${NC}"
  116. else
  117. echo -e "3307 | MySQL Database Node | ${RED}OFFLINE${NC}"
  118. fi
  119. # Check Ollama on 11434
  120. if nc -z localhost 11434 2>/dev/null; then
  121. echo -e "11434 | Ollama AI Engine | ${GREEN}ONLINE${NC}"
  122. else
  123. echo -e "11434 | Ollama AI Engine | ${RED}OFFLINE${NC}"
  124. fi
  125. # Check Nginx Gateway on 80
  126. if nc -z localhost 80 2>/dev/null; then
  127. echo -e "80 | Nginx Gateway (HTTP Proxy) | ${GREEN}ONLINE${NC}"
  128. else
  129. echo -e "80 | Nginx Gateway (HTTP Proxy) | ${RED}OFFLINE${NC}"
  130. fi
  131. # Check Zabbix Web UI on 8081
  132. if nc -z localhost 8081 2>/dev/null; then
  133. echo -e "8081 | Zabbix Dashboard | ${GREEN}ONLINE${NC}"
  134. else
  135. echo -e "8081 | Zabbix Dashboard | ${RED}OFFLINE${NC}"
  136. fi
  137. echo "---------------------------------------------------------"
  138. }
  139. show_help() {
  140. echo "Usage: $0 {start|stop|restart|status}"
  141. echo " start - Deploy and wake up all services sequentially according to priorities."
  142. echo " stop - Gracefully turn off containers in reverse dependency order."
  143. echo " restart - Perform sequential shutdown followed by sequential boot."
  144. echo " status - Print container status and inspect physical TCP port sockets."
  145. exit 1
  146. }
  147. case "$1" in
  148. start)
  149. start_services
  150. ;;
  151. stop)
  152. stop_services
  153. ;;
  154. restart)
  155. stop_services
  156. start_services
  157. ;;
  158. status)
  159. check_status
  160. ;;
  161. *)
  162. show_help
  163. ;;
  164. esac