#!/bin/bash # PHP-FPM Server Manager Module # Orchestrates large-scale server operations: scanning, planning, executing, reporting # Part of PHP Optimizer - Phase 3 Refactoring # ============================================================================ # SERVER SCANNING & INVENTORY # ============================================================================ # Scan entire server and collect comprehensive information scan_entire_server() { local filter_mode="${1:-all}" # all, user, pattern, traffic, needs_optimization local filter_arg="${2:-}" init_change_tracking local -a domains_to_analyze case "$filter_mode" in all) mapfile -t domains_to_analyze < <(enumerate_all_domains) ;; user) [ -z "$filter_arg" ] && return 1 mapfile -t domains_to_analyze < <(enumerate_user_domains "$filter_arg") ;; pattern) [ -z "$filter_arg" ] && return 1 mapfile -t domains_to_analyze < <(filter_domains_by_name "$filter_arg") ;; traffic) [ -z "$filter_arg" ] && filter_arg="100" mapfile -t domains_to_analyze < <(filter_domains_by_traffic "$filter_arg" "above") ;; needs_optimization) mapfile -t domains_to_analyze < <(filter_domains_by_optimization_status "needs_optimization") ;; *) return 1 ;; esac local total_domains=${#domains_to_analyze[@]} local current=0 local -A scan_results if [ "$total_domains" -eq 0 ]; then return 0 fi for domain in "${domains_to_analyze[@]}"; do [ -z "$domain" ] && continue current=$((current + 1)) show_enumeration_progress "$current" "$total_domains" # Collect domain info local owner owner=$(find_domain_owner "$domain") local issues issues=$(detect_php_config_issues "$owner" "$domain" 2>/dev/null || echo "") local issue_count issue_count=$(echo "$issues" | grep -c "^" || echo "0") scan_results["$domain"]="$owner|$issue_count|$issues" done echo "" # Output results in scannable format for domain in "${!scan_results[@]}"; do echo "DOMAIN|$domain|${scan_results[$domain]}" done return 0 } # Analyze entire server for optimization opportunities analyze_entire_server() { local -a all_domains mapfile -t all_domains < <(enumerate_all_domains) local total_domains=${#all_domains[@]} local domains_with_issues=0 local critical_count=0 local high_count=0 local medium_count=0 local low_count=0 local current=0 for domain in "${all_domains[@]}"; do [ -z "$domain" ] && continue current=$((current + 1)) display_progress "$current" "$total_domains" "Analyzing" local owner owner=$(find_domain_owner "$domain") if [ -z "$owner" ]; then continue fi # Detect issues local issues issues=$(detect_php_config_issues "$owner" "$domain" 2>/dev/null) # Count issues by severity local c_count h_count m_count l_count c_count=$(echo "$issues" | grep -c "^[^|]*|CRITICAL|" || echo "0") h_count=$(echo "$issues" | grep -c "^[^|]*|HIGH|" || echo "0") m_count=$(echo "$issues" | grep -c "^[^|]*|MEDIUM|" || echo "0") l_count=$(echo "$issues" | grep -c "^[^|]*|LOW|" || echo "0") if [ $((c_count + h_count + m_count + l_count)) -gt 0 ]; then domains_with_issues=$((domains_with_issues + 1)) critical_count=$((critical_count + c_count)) high_count=$((high_count + h_count)) medium_count=$((medium_count + m_count)) low_count=$((low_count + l_count)) fi done echo "" echo "$total_domains|$domains_with_issues|$critical_count|$high_count|$medium_count|$low_count" } # ============================================================================ # OPTIMIZATION PLANNING # ============================================================================ # Plan optimizations for entire server plan_server_optimizations() { local filter_mode="${1:-needs_optimization}" local filter_arg="${2:-}" local dry_run="${3:-true}" local -a domains_to_optimize mapfile -t domains_to_optimize < <(scan_entire_server "$filter_mode" "$filter_arg") local total_domains=0 local optimization_count=0 # Parse scan results and identify optimization opportunities declare -A optimization_plan while IFS='|' read -r type domain owner issue_count rest; do [ "$type" != "DOMAIN" ] && continue [ -z "$domain" ] && continue total_domains=$((total_domains + 1)) if [ "$issue_count" -gt 0 ]; then optimization_count=$((optimization_count + 1)) optimization_plan["$domain"]="$owner|$issue_count" fi done <<< "$(echo "${domains_to_optimize[@]}" | tr ' ' '\n')" # Generate plan summary echo "OPTIMIZATION_PLAN" echo "Total domains: $total_domains" echo "Domains needing optimization: $optimization_count" echo "" # List domains to be optimized for domain in "${!optimization_plan[@]}"; do local owner issue_count owner=$(echo "${optimization_plan[$domain]}" | cut -d'|' -f1) issue_count=$(echo "${optimization_plan[$domain]}" | cut -d'|' -f2) echo " - $domain (owner: $owner, $issue_count issues)" done return 0 } # ============================================================================ # OPTIMIZATION EXECUTION # ============================================================================ # Execute planned optimizations across server execute_server_optimization_plan() { local -a domains=("$@") local dry_run="${DRY_RUN:-false}" local require_confirmation="${REQUIRE_CONFIRMATION:-true}" if [ ${#domains[@]} -eq 0 ]; then return 1 fi # Show summary before executing local total=${#domains[@]} echo "" echo "Server Optimization Summary:" echo " Total domains to optimize: $total" echo " Dry-run mode: $dry_run" echo "" if [ "$require_confirmation" = "true" ]; then if ! confirm "Execute optimizations for $total domain(s)?"; then return 1 fi fi init_change_tracking local successful=0 local failed=0 local current=0 for domain in "${domains[@]}"; do [ -z "$domain" ] && continue current=$((current + 1)) display_progress "$current" "$total" "Optimizing" local owner owner=$(find_domain_owner "$domain") if [ -z "$owner" ]; then failed=$((failed + 1)) log_change "$domain" "server_optimization" "unknown_owner" "skipped" "failed" continue fi # Apply optimizations if apply_optimization "$domain" "$owner" "all" "$dry_run"; then successful=$((successful + 1)) else failed=$((failed + 1)) fi done echo "" echo "Optimization Results:" echo " Successful: $successful" echo " Failed: $failed" echo " Total: $((successful + failed))" # Reload PHP-FPM once for all changes if [ "$dry_run" != "true" ] && [ "$successful" -gt 0 ]; then echo "Reloading PHP-FPM to apply changes..." reload_php_fpm fi return $((failed > 0 ? 1 : 0)) } # ============================================================================ # REPORTING # ============================================================================ # Generate comprehensive server analysis report generate_server_report() { local report_file="${1:-/tmp/php-optimizer-server-report-$(date +%Y%m%d-%H%M%S).txt}" local filter_mode="${2:-all}" local filter_arg="${3:-}" { echo "╔════════════════════════════════════════════════════════════════════════╗" echo "║ PHP-FPM SERVER ANALYSIS REPORT ║" echo "╚════════════════════════════════════════════════════════════════════════╝" echo "" echo "Generated: $(date)" echo "" # Server Information echo "═══════════════════════════════════════════════════════════════════════════" echo "SERVER INFORMATION" echo "═══════════════════════════════════════════════════════════════════════════" echo "" echo "Total RAM: $(free -h | awk '/^Mem:/ {print $2}')" echo "CPU Cores: $(nproc)" echo "Total Accounts: $(get_total_account_count)" echo "Total Domains: $(get_total_domain_count)" echo "" # Analysis Results echo "═══════════════════════════════════════════════════════════════════════════" echo "ANALYSIS RESULTS" echo "═══════════════════════════════════════════════════════════════════════════" echo "" local analysis_result analysis_result=$(analyze_entire_server) local total_domains domains_with_issues critical high medium low total_domains=$(echo "$analysis_result" | cut -d'|' -f1) domains_with_issues=$(echo "$analysis_result" | cut -d'|' -f2) critical=$(echo "$analysis_result" | cut -d'|' -f3) high=$(echo "$analysis_result" | cut -d'|' -f4) medium=$(echo "$analysis_result" | cut -d'|' -f5) low=$(echo "$analysis_result" | cut -d'|' -f6) echo "Total Domains Analyzed: $total_domains" echo "Domains with Issues: $domains_with_issues" echo "" echo "Issue Summary:" echo " CRITICAL: $critical" echo " HIGH: $high" echo " MEDIUM: $medium" echo " LOW: $low" echo "" # Health Status echo "═══════════════════════════════════════════════════════════════════════════" echo "SERVER HEALTH STATUS" echo "═══════════════════════════════════════════════════════════════════════════" echo "" local capacity_result capacity_result=$(calculate_server_memory_capacity 2>/dev/null) local total_required_mb total_ram_mb percentage status total_required_mb=$(echo "$capacity_result" | head -1 | cut -d'|' -f1) total_ram_mb=$(echo "$capacity_result" | head -1 | cut -d'|' -f2) percentage=$(echo "$capacity_result" | head -1 | cut -d'|' -f3) status=$(echo "$capacity_result" | head -1 | cut -d'|' -f4) echo "Total Server RAM: ${total_ram_mb}MB" echo "Current FPM Capacity: ${total_required_mb}MB (${percentage}% of RAM)" echo "Server Status: $status" echo "" # Recommendations echo "═══════════════════════════════════════════════════════════════════════════" echo "RECOMMENDATIONS" echo "═══════════════════════════════════════════════════════════════════════════" echo "" if [ "$domains_with_issues" -gt 0 ]; then echo "1. Apply recommended optimizations to $domains_with_issues domain(s)" if [ "$critical" -gt 0 ]; then echo " - URGENT: Address $critical CRITICAL issue(s)" fi if [ "$high" -gt 0 ]; then echo " - HIGH PRIORITY: Address $high HIGH severity issue(s)" fi else echo "No issues detected - server configuration is optimal" fi case "$status" in CRITICAL) echo "2. URGENT: Review memory allocation - server at OOM risk!" ;; WARNING) echo "2. Review memory allocation - consider reducing max_children" ;; CAUTION) echo "2. Monitor memory usage - consider minor adjustments" ;; HEALTHY) echo "2. Continue monitoring - no immediate action needed" ;; esac echo "" # Change History (if available) if [ -n "$EXECUTOR_CHANGE_LOG" ] && [ -f "$EXECUTOR_CHANGE_LOG" ]; then echo "═══════════════════════════════════════════════════════════════════════════" echo "RECENT CHANGES" echo "═══════════════════════════════════════════════════════════════════════════" echo "" tail -20 "$EXECUTOR_CHANGE_LOG" echo "" fi # Footer echo "═══════════════════════════════════════════════════════════════════════════" echo "Report generated by PHP-FPM Optimizer - Phase 3" echo "═══════════════════════════════════════════════════════════════════════════" } | tee "$report_file" echo "" echo "Report saved to: $report_file" } # Generate domain-specific report generate_domain_report() { local domain="$1" local report_file="${2:-/tmp/php-optimizer-${domain}-report-$(date +%Y%m%d-%H%M%S).txt}" local owner owner=$(find_domain_owner "$domain") if [ -z "$owner" ]; then return 1 fi { echo "╔════════════════════════════════════════════════════════════════════════╗" echo "║ PHP-FPM DOMAIN ANALYSIS REPORT ║" echo "╚════════════════════════════════════════════════════════════════════════╝" echo "" echo "Domain: $domain" echo "Owner: $owner" echo "Generated: $(date)" echo "" # Domain Information echo "═══════════════════════════════════════════════════════════════════════════" echo "DOMAIN INFORMATION" echo "═══════════════════════════════════════════════════════════════════════════" echo "" local pool_config pool_config=$(find_fpm_pool_config "$owner" "$domain" 2>/dev/null) if [ -n "$pool_config" ]; then echo "Pool Config: $pool_config" echo "" echo "Current Settings:" grep "^pm" "$pool_config" | sed 's/^/ /' echo "" fi # Analysis echo "═══════════════════════════════════════════════════════════════════════════" echo "ANALYSIS" echo "═══════════════════════════════════════════════════════════════════════════" echo "" local issues issues=$(detect_php_config_issues "$owner" "$domain" 2>/dev/null) if [ -z "$issues" ] || [ "$(echo "$issues" | wc -l)" -eq 0 ]; then echo "No issues detected - configuration is optimal" else echo "Issues Found:" echo "" while IFS='|' read -r issue_type severity message recommendation; do [ -z "$issue_type" ] && continue echo "[$severity] $message" echo " → $recommendation" echo "" done <<< "$issues" fi # Recommendations echo "═══════════════════════════════════════════════════════════════════════════" echo "RECOMMENDATIONS" echo "═══════════════════════════════════════════════════════════════════════════" echo "" local total_ram_mb total_ram_mb=$(free -m | awk '/^Mem:/ {print $2}') local improved_result improved_result=$(calculate_optimal_php_settings "$owner" "$total_ram_mb" 2>/dev/null) if [ -n "$improved_result" ]; then local improved_max_children improved_pm_mode improved_reason improved_max_children=$(echo "$improved_result" | cut -d'|' -f1) improved_pm_mode=$(echo "$improved_result" | cut -d'|' -f2) improved_reason=$(echo "$improved_result" | cut -d'|' -f5) echo "Recommended pm.max_children: $improved_max_children" echo "Recommended pm mode: $improved_pm_mode" echo "Reason: $improved_reason" fi echo "" } | tee "$report_file" echo "Report saved to: $report_file" } # ============================================================================ # BATCH OPERATIONS # ============================================================================ # Perform batch operation on multiple domains batch_operation() { local operation="$1" # optimize, analyze, health_check local filter_mode="${2:-needs_optimization}" local filter_arg="${3:-}" local require_confirmation="${4:-true}" local -a target_domains mapfile -t target_domains < <(scan_entire_server "$filter_mode" "$filter_arg") case "$operation" in optimize) echo "Planning server-wide optimization..." plan_server_optimizations "$filter_mode" "$filter_arg" if [ "$require_confirmation" = "true" ]; then if ! confirm "Execute optimizations?"; then return 1 fi fi execute_server_optimization_plan "${target_domains[@]}" ;; analyze) echo "Analyzing entire server..." analyze_entire_server ;; health_check) echo "Performing health check on all domains..." init_change_tracking local total=${#target_domains[@]} local current=0 for domain in "${target_domains[@]}"; do [ -z "$domain" ] && continue current=$((current + 1)) display_progress "$current" "$total" local owner owner=$(find_domain_owner "$domain") [ -n "$owner" ] && perform_health_check "$owner" "$domain" >/dev/null 2>&1 done echo "" ;; esac return $? } # ============================================================================ # EXPORT ALL FUNCTIONS # ============================================================================ export -f scan_entire_server export -f analyze_entire_server export -f plan_server_optimizations export -f execute_server_optimization_plan export -f generate_server_report export -f generate_domain_report export -f batch_operation