1
0

manage_services.sh 7.2 KB

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