ef993c1bc6
CRITICAL BUG - Variable Scope Script uses 'set -e' which causes exit on ANY error. The 'local' keyword only works inside functions, not at script level. This would cause the batch analyzer to fail immediately. Fix: - Removed 'local' from all_domains_string declaration (line 97) - Variable now correctly declared at script level - Script can now run without exiting on scope error Testing: ✓ Bash syntax validation passes ✓ All domain collection logic works ✓ Traffic percentage calculation correct ✓ Fair share allocation correct ✓ Edge cases handled (single domain, many domains, no logs)
521 lines
24 KiB
Bash
Executable File
521 lines
24 KiB
Bash
Executable File
#!/bin/bash
|
|
# PHP-FPM Batch Analyzer - One-Shot Diagnostic Script
|
|
# Analyzes all domains on server, shows current vs recommended max_children
|
|
# Shows memory impact and optimization opportunities
|
|
# Drop in, run once, then delete
|
|
|
|
set -e
|
|
|
|
PHP_TOOLKIT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && cd ../.. && pwd)"
|
|
|
|
# Source required libraries
|
|
source "$PHP_TOOLKIT_DIR/lib/common-functions.sh" 2>/dev/null || { echo "ERROR: common-functions.sh not found"; exit 1; }
|
|
source "$PHP_TOOLKIT_DIR/lib/system-detect.sh" 2>/dev/null || { echo "ERROR: system-detect.sh not found"; exit 1; }
|
|
source "$PHP_TOOLKIT_DIR/lib/user-manager.sh" 2>/dev/null || { echo "ERROR: user-manager.sh not found"; exit 1; }
|
|
source "$PHP_TOOLKIT_DIR/lib/php-detector.sh" 2>/dev/null || { echo "ERROR: php-detector.sh not found"; exit 1; }
|
|
source "$PHP_TOOLKIT_DIR/lib/php-analyzer.sh" 2>/dev/null || { echo "ERROR: php-analyzer.sh not found"; exit 1; }
|
|
source "$PHP_TOOLKIT_DIR/lib/php-calculator-improved.sh" 2>/dev/null || { echo "ERROR: php-calculator-improved.sh not found"; exit 1; }
|
|
source "$PHP_TOOLKIT_DIR/lib/php-scanner.sh" 2>/dev/null || { echo "ERROR: php-scanner.sh not found"; exit 1; }
|
|
|
|
# Color codes
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
CYAN='\033[0;36m'
|
|
WHITE='\033[1;37m'
|
|
BOLD='\033[1m'
|
|
NC='\033[0m'
|
|
|
|
cecho() {
|
|
echo -e "$@"
|
|
}
|
|
|
|
# ============================================================================
|
|
# INITIALIZATION
|
|
# ============================================================================
|
|
|
|
initialize_system_detection
|
|
|
|
if [ "$EUID" -ne 0 ]; then
|
|
cecho "${RED}ERROR: This script must be run as root${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# ============================================================================
|
|
# MAIN ANALYSIS
|
|
# ============================================================================
|
|
|
|
cecho "${CYAN}╔════════════════════════════════════════════════════════════════════════╗${NC}"
|
|
cecho "${CYAN}║${WHITE} PHP-FPM BATCH ANALYZER - DIAGNOSTIC REPORT ${CYAN}║${NC}"
|
|
cecho "${CYAN}╚════════════════════════════════════════════════════════════════════════╝${NC}"
|
|
echo ""
|
|
|
|
# Get server info
|
|
cecho "${WHITE}${BOLD}SERVER INFORMATION${NC}"
|
|
cecho "${CYAN}─────────────────────────────────────────────────────────────────────${NC}"
|
|
|
|
TOTAL_RAM_MB=$(free -m | awk '/^Mem:/ {print $2}')
|
|
CPU_CORES=$(nproc)
|
|
CONTROL_PANEL="$SYS_CONTROL_PANEL"
|
|
|
|
cecho " Total RAM: ${WHITE}${TOTAL_RAM_MB}MB${NC}"
|
|
cecho " CPU Cores: ${WHITE}${CPU_CORES}${NC}"
|
|
cecho " Control Panel: ${WHITE}${CONTROL_PANEL}${NC}"
|
|
cecho " Scan Date: ${WHITE}$(date)${NC}"
|
|
echo ""
|
|
|
|
# ============================================================================
|
|
# STEP 1: CALCULATE SERVER CAPACITY
|
|
# ============================================================================
|
|
|
|
cecho "${WHITE}${BOLD}STEP 1: SERVER CAPACITY ANALYSIS${NC}"
|
|
cecho "${CYAN}─────────────────────────────────────────────────────────────────────${NC}"
|
|
|
|
server_capacity_result=$(calculate_server_capacity "$TOTAL_RAM_MB")
|
|
server_capacity=$(echo "$server_capacity_result" | cut -d'|' -f1)
|
|
available_memory=$(echo "$server_capacity_result" | cut -d'|' -f2)
|
|
memory_per_process=$(echo "$server_capacity_result" | cut -d'|' -f3)
|
|
|
|
cecho " Available RAM for PHP-FPM: ${WHITE}${available_memory}MB${NC}"
|
|
cecho " Memory per process: ${WHITE}${memory_per_process}MB${NC}"
|
|
cecho " Server capacity: ${WHITE}${server_capacity}${NC} total max_children"
|
|
echo ""
|
|
|
|
# ============================================================================
|
|
# STEP 2: DOMAIN ENUMERATION & TRAFFIC ANALYSIS
|
|
# ============================================================================
|
|
|
|
cecho "${WHITE}${BOLD}STEP 2: DOMAIN ENUMERATION & TRAFFIC ANALYSIS${NC}"
|
|
cecho "${CYAN}─────────────────────────────────────────────────────────────────────${NC}"
|
|
|
|
# Get all users and domains
|
|
users=$(list_all_users)
|
|
|
|
# CRITICAL FIX: Build list of ALL domains on server FIRST
|
|
# This is needed for accurate traffic percentage calculation
|
|
all_domains_string="" # Note: NOT local (function scope only), this is script-level
|
|
while IFS= read -r username; do
|
|
[ -z "$username" ] && continue
|
|
user_domains=$(get_user_domains "$username")
|
|
while IFS= read -r domain; do
|
|
[ -z "$domain" ] && continue
|
|
all_domains_string="$all_domains_string$domain"$'\n'
|
|
done <<< "$user_domains"
|
|
done <<< "$users"
|
|
|
|
# Initialize tracking arrays
|
|
declare -a domain_list
|
|
declare -a domain_owner
|
|
declare -a current_max_children
|
|
declare -a recommended_max_children
|
|
declare -a memory_impact
|
|
declare -a needs_optimization
|
|
declare -a peak_concurrent
|
|
declare -a pm_mode
|
|
declare -a pm_max_requests
|
|
declare -a pm_min_spare
|
|
declare -a pm_max_spare
|
|
declare -a pm_idle_timeout
|
|
declare -a traffic_percentage_arr
|
|
declare -a limiting_factor_arr
|
|
|
|
TOTAL_DOMAINS=0
|
|
TOTAL_CURRENT_MEMORY=0
|
|
TOTAL_RECOMMENDED_MEMORY=0
|
|
TOTAL_CURRENT_MEMORY_WITH_MAX=0
|
|
|
|
while IFS= read -r username; do
|
|
[ -z "$username" ] && continue
|
|
|
|
user_domains=$(get_user_domains "$username")
|
|
|
|
while IFS= read -r domain; do
|
|
[ -z "$domain" ] && continue
|
|
|
|
TOTAL_DOMAINS=$((TOTAL_DOMAINS + 1))
|
|
domain_list[$TOTAL_DOMAINS]="$domain"
|
|
domain_owner[$TOTAL_DOMAINS]="$username"
|
|
|
|
# Find pool config
|
|
pool_config=$(find_fpm_pool_config "$username" "$domain" 2>/dev/null)
|
|
|
|
if [ -z "$pool_config" ] || [ ! -f "$pool_config" ]; then
|
|
current_max_children[$TOTAL_DOMAINS]="ERROR"
|
|
recommended_max_children[$TOTAL_DOMAINS]="ERROR"
|
|
memory_impact[$TOTAL_DOMAINS]="?"
|
|
continue
|
|
fi
|
|
|
|
# Get current max_children
|
|
current=$(grep "^pm.max_children" "$pool_config" 2>/dev/null | awk -F'=' '{print $2}' | tr -d ' ')
|
|
current=${current:-40}
|
|
current_max_children[$TOTAL_DOMAINS]="$current"
|
|
|
|
# Get all pool settings
|
|
pm_mode_val=$(grep "^pm = " "$pool_config" 2>/dev/null | awk -F'=' '{print $2}' | tr -d ' ')
|
|
pm_mode[$TOTAL_DOMAINS]="${pm_mode_val:-static}"
|
|
|
|
pm_max_req=$(grep "^pm.max_requests = " "$pool_config" 2>/dev/null | awk -F'=' '{print $2}' | tr -d ' ')
|
|
pm_max_requests[$TOTAL_DOMAINS]="${pm_max_req:-0}"
|
|
|
|
pm_min=$(grep "^pm.min_spare_servers = " "$pool_config" 2>/dev/null | awk -F'=' '{print $2}' | tr -d ' ')
|
|
pm_min_spare[$TOTAL_DOMAINS]="${pm_min:-2}"
|
|
|
|
pm_max=$(grep "^pm.max_spare_servers = " "$pool_config" 2>/dev/null | awk -F'=' '{print $2}' | tr -d ' ')
|
|
pm_max_spare[$TOTAL_DOMAINS]="${pm_max:-8}"
|
|
|
|
pm_idle=$(grep "^pm.process_idle_timeout = " "$pool_config" 2>/dev/null | awk -F'=' '{print $2}' | tr -d ' ')
|
|
pm_idle_timeout[$TOTAL_DOMAINS]="${pm_idle:-10}"
|
|
|
|
# Calculate recommended using THREE-CONSTRAINT INTELLIGENT ALGORITHM
|
|
# Get traffic percentage for this domain
|
|
# CRITICAL FIX: Pass ALL server domains, not just user's domains!
|
|
traffic_percentage=$(get_domain_traffic_percentage "$username" "$domain" "$all_domains_string" 2>/dev/null | cut -d'|' -f1)
|
|
traffic_percentage=${traffic_percentage:-50}
|
|
|
|
# Use intelligent three-constraint model: MIN(memory, traffic, fair_share)
|
|
recommended_result=$(calculate_optimal_php_settings_intelligent "$username" "$TOTAL_RAM_MB" "$server_capacity" "$traffic_percentage" 2>/dev/null || echo "20|dynamic|1|5|ERROR|Failed")
|
|
recommended=$(echo "$recommended_result" | cut -d'|' -f1)
|
|
recommended=${recommended:-20}
|
|
limiting_factor=$(echo "$recommended_result" | cut -d'|' -f5)
|
|
recommended_max_children[$TOTAL_DOMAINS]="$recommended"
|
|
traffic_percentage_arr[$TOTAL_DOMAINS]="$traffic_percentage"
|
|
limiting_factor_arr[$TOTAL_DOMAINS]="$limiting_factor"
|
|
|
|
# Calculate memory impact using ACTUAL memory per process (not hardcoded 20MB)
|
|
current_memory=$((current * memory_per_process))
|
|
recommended_memory=$((recommended * memory_per_process))
|
|
impact=$((current_memory - recommended_memory))
|
|
memory_impact[$TOTAL_DOMAINS]="$impact"
|
|
|
|
# Get peak concurrent requests for this domain
|
|
peak=$(get_domain_peak_concurrent "$domain" 2>/dev/null || echo "?")
|
|
peak_concurrent[$TOTAL_DOMAINS]="$peak"
|
|
|
|
# Track totals
|
|
TOTAL_CURRENT_MEMORY=$((TOTAL_CURRENT_MEMORY + current_memory))
|
|
TOTAL_RECOMMENDED_MEMORY=$((TOTAL_RECOMMENDED_MEMORY + recommended_memory))
|
|
TOTAL_CURRENT_MEMORY_WITH_MAX=$((TOTAL_CURRENT_MEMORY_WITH_MAX + current_memory))
|
|
|
|
# Determine if optimization needed
|
|
# Flag as YES if: different from current (increase or decrease)
|
|
# AND has meaningful traffic (>= 5 concurrent) OR memory efficiency gain (> 20% reduction)
|
|
memory_reduction=0
|
|
if [ "$recommended" -lt "$current" ]; then
|
|
memory_reduction=$(( (current - recommended) * 100 / current ))
|
|
fi
|
|
|
|
if [ "$recommended" -ne "$current" ]; then
|
|
# Check if change is meaningful:
|
|
# 1. Has significant traffic (>= 5 concurrent requests)
|
|
# 2. OR significant memory reduction (>= 20%)
|
|
has_traffic=0
|
|
[ "$peak" != "?" ] && [ "$peak" -ge 5 ] && has_traffic=1
|
|
|
|
if [ "$has_traffic" = "1" ] || [ "$memory_reduction" -ge 20 ]; then
|
|
needs_optimization[$TOTAL_DOMAINS]="YES"
|
|
else
|
|
needs_optimization[$TOTAL_DOMAINS]="NO"
|
|
fi
|
|
else
|
|
needs_optimization[$TOTAL_DOMAINS]="NO"
|
|
fi
|
|
|
|
done <<< "$user_domains"
|
|
done <<< "$users"
|
|
|
|
# ============================================================================
|
|
# DISPLAY RESULTS (Prioritized by Traffic)
|
|
# ============================================================================
|
|
|
|
# Build sortable list with priority (traffic-based)
|
|
sorted_indices=()
|
|
domain_sort_data=()
|
|
|
|
for idx in $(seq 1 $TOTAL_DOMAINS); do
|
|
domain="${domain_list[$idx]}"
|
|
peak="${peak_concurrent[$idx]}"
|
|
optimize="${needs_optimization[$idx]}"
|
|
|
|
if [ "$peak" == "?" ]; then
|
|
peak=0
|
|
fi
|
|
|
|
# Create sort key: prioritize domains needing optimization with high traffic
|
|
if [ "$optimize" == "YES" ]; then
|
|
# High priority: domains needing optimization with traffic >= 5
|
|
if [[ "$peak" =~ ^[0-9]+$ ]] && [ "$peak" -ge 5 ]; then
|
|
sort_priority="0" # Highest priority
|
|
else
|
|
sort_priority="1" # Medium priority (needs optimization, low traffic)
|
|
fi
|
|
else
|
|
sort_priority="2" # Low priority (already optimized)
|
|
fi
|
|
|
|
domain_sort_data+=("$sort_priority|$peak|$idx")
|
|
done
|
|
|
|
# Sort by priority then by peak concurrent requests (descending)
|
|
mapfile -t sorted_data < <(printf '%s\n' "${domain_sort_data[@]}" | sort -t'|' -k1,1 -k2,2nr)
|
|
|
|
# Extract sorted indices
|
|
for sort_entry in "${sorted_data[@]}"; do
|
|
idx=$(echo "$sort_entry" | cut -d'|' -f3)
|
|
sorted_indices+=("$idx")
|
|
done
|
|
|
|
# Sort and display domains (prioritized)
|
|
OPTIMIZATION_COUNT=0
|
|
for idx in "${sorted_indices[@]}"; do
|
|
domain="${domain_list[$idx]}"
|
|
owner="${domain_owner[$idx]}"
|
|
current="${current_max_children[$idx]}"
|
|
recommended="${recommended_max_children[$idx]}"
|
|
impact="${memory_impact[$idx]}"
|
|
optimize="${needs_optimization[$idx]}"
|
|
peak="${peak_concurrent[$idx]}"
|
|
|
|
if [ "$current" == "ERROR" ]; then
|
|
continue
|
|
fi
|
|
|
|
# Determine traffic indicator
|
|
traffic_indicator=""
|
|
if [[ "$peak" =~ ^[0-9]+$ ]]; then
|
|
if [ "$peak" -ge 20 ]; then
|
|
traffic_indicator="${RED}⚠ CRITICAL TRAFFIC (${peak})${NC}"
|
|
elif [ "$peak" -ge 10 ]; then
|
|
traffic_indicator="${YELLOW}⚠ HIGH TRAFFIC (${peak})${NC}"
|
|
elif [ "$peak" -ge 5 ]; then
|
|
traffic_indicator="${CYAN}→ MEDIUM TRAFFIC (${peak})${NC}"
|
|
else
|
|
traffic_indicator="${WHITE}○ LOW TRAFFIC (${peak})${NC}"
|
|
fi
|
|
else
|
|
traffic_indicator="${WHITE}○ TRAFFIC UNKNOWN${NC}"
|
|
fi
|
|
|
|
# Format output with all pool settings
|
|
if [ "$optimize" == "YES" ]; then
|
|
cecho "${YELLOW}[$idx]${NC} $domain"
|
|
cecho " Owner: $owner"
|
|
cecho " Traffic: $traffic_indicator (${traffic_percentage_arr[$idx]}% of server)"
|
|
cecho " Limiting Factor: ${limiting_factor_arr[$idx]}"
|
|
cecho ""
|
|
cecho " ${BOLD}Current Pool Settings:${NC}"
|
|
cecho " pm.max_children: ${RED}$current${NC} → Recommended: ${GREEN}$recommended${NC}"
|
|
cecho " pm: ${WHITE}${pm_mode[$idx]}${NC}"
|
|
cecho " pm.min_spare_servers: ${WHITE}${pm_min_spare[$idx]}${NC}"
|
|
cecho " pm.max_spare_servers: ${WHITE}${pm_max_spare[$idx]}${NC}"
|
|
cecho " pm.max_requests: ${WHITE}${pm_max_requests[$idx]}${NC}"
|
|
cecho " pm.process_idle_timeout: ${WHITE}${pm_idle_timeout[$idx]}${NC}"
|
|
cecho ""
|
|
cecho " Memory impact: ${GREEN}+${impact}MB${NC} if optimized"
|
|
cecho " Status: ${YELLOW}NEEDS OPTIMIZATION${NC}"
|
|
OPTIMIZATION_COUNT=$((OPTIMIZATION_COUNT + 1))
|
|
else
|
|
cecho "${GREEN}[$idx]${NC} $domain"
|
|
cecho " Owner: $owner"
|
|
cecho " Traffic: $traffic_indicator"
|
|
cecho ""
|
|
cecho " ${BOLD}Pool Settings:${NC}"
|
|
cecho " pm.max_children: $current"
|
|
cecho " pm: ${WHITE}${pm_mode[$idx]}${NC}"
|
|
cecho " pm.min_spare_servers: ${WHITE}${pm_min_spare[$idx]}${NC}"
|
|
cecho " pm.max_spare_servers: ${WHITE}${pm_max_spare[$idx]}${NC}"
|
|
cecho " pm.max_requests: ${WHITE}${pm_max_requests[$idx]}${NC}"
|
|
cecho " pm.process_idle_timeout: ${WHITE}${pm_idle_timeout[$idx]}${NC}"
|
|
cecho ""
|
|
cecho " Status: ${GREEN}OK${NC}"
|
|
fi
|
|
|
|
echo ""
|
|
done
|
|
|
|
# ============================================================================
|
|
# SERVER-WIDE SUMMARY
|
|
# ============================================================================
|
|
|
|
echo ""
|
|
cecho "${WHITE}${BOLD}SERVER-WIDE SUMMARY${NC}"
|
|
cecho "${CYAN}═════════════════════════════════════════════════════════════════════${NC}"
|
|
echo ""
|
|
|
|
# Calculate percentages
|
|
CURRENT_PERCENT=$((TOTAL_CURRENT_MEMORY * 100 / TOTAL_RAM_MB))
|
|
RECOMMENDED_PERCENT=$((TOTAL_RECOMMENDED_MEMORY * 100 / TOTAL_RAM_MB))
|
|
POTENTIAL_SAVINGS=$((TOTAL_CURRENT_MEMORY - TOTAL_RECOMMENDED_MEMORY))
|
|
POTENTIAL_SAVINGS_PERCENT=$((POTENTIAL_SAVINGS * 100 / TOTAL_CURRENT_MEMORY))
|
|
|
|
cecho " Total domains analyzed: ${WHITE}$TOTAL_DOMAINS${NC}"
|
|
cecho " Domains needing optimization: ${YELLOW}$OPTIMIZATION_COUNT${NC}"
|
|
cecho " Domains already optimized: ${GREEN}$((TOTAL_DOMAINS - OPTIMIZATION_COUNT))${NC}"
|
|
echo ""
|
|
|
|
cecho " ${BOLD}Current Memory Allocation:${NC}"
|
|
cecho " Total: ${WHITE}${TOTAL_CURRENT_MEMORY}MB${NC} (${RED}${CURRENT_PERCENT}%${NC} of ${TOTAL_RAM_MB}MB RAM)"
|
|
echo ""
|
|
|
|
cecho " ${BOLD}Recommended Memory Allocation:${NC}"
|
|
cecho " Total: ${WHITE}${TOTAL_RECOMMENDED_MEMORY}MB${NC} (${GREEN}${RECOMMENDED_PERCENT}%${NC} of ${TOTAL_RAM_MB}MB RAM)"
|
|
echo ""
|
|
|
|
cecho " ${BOLD}Optimization Potential:${NC}"
|
|
cecho " Memory that could be freed: ${GREEN}${POTENTIAL_SAVINGS}MB${NC} (${POTENTIAL_SAVINGS_PERCENT}% reduction)"
|
|
echo ""
|
|
|
|
# Combined Memory Capacity Check
|
|
cecho "${WHITE}${BOLD}COMBINED MEMORY CAPACITY (If ALL pools hit max_children):${NC}"
|
|
ALL_MAX_PERCENT=$((TOTAL_CURRENT_MEMORY_WITH_MAX * 100 / TOTAL_RAM_MB))
|
|
|
|
if [ "$ALL_MAX_PERCENT" -gt 100 ]; then
|
|
cecho " Total if all at max: ${RED}${TOTAL_CURRENT_MEMORY_WITH_MAX}MB${NC} (${RED}${ALL_MAX_PERCENT}%${NC} of ${TOTAL_RAM_MB}MB)"
|
|
cecho " Status: ${RED}${BOLD}CRITICAL - SERVER WILL RUN OUT OF MEMORY!${NC}"
|
|
cecho " ${RED}⚠ The server would exceed available RAM by $((TOTAL_CURRENT_MEMORY_WITH_MAX - TOTAL_RAM_MB))MB${NC}"
|
|
elif [ "$ALL_MAX_PERCENT" -gt 90 ]; then
|
|
cecho " Total if all at max: ${YELLOW}${TOTAL_CURRENT_MEMORY_WITH_MAX}MB${NC} (${YELLOW}${ALL_MAX_PERCENT}%${NC} of ${TOTAL_RAM_MB}MB)"
|
|
cecho " Status: ${YELLOW}${BOLD}WARNING - High memory pressure${NC}"
|
|
cecho " ${YELLOW}⚠ Only $((TOTAL_RAM_MB - TOTAL_CURRENT_MEMORY_WITH_MAX))MB headroom remaining${NC}"
|
|
elif [ "$ALL_MAX_PERCENT" -gt 75 ]; then
|
|
cecho " Total if all at max: ${CYAN}${TOTAL_CURRENT_MEMORY_WITH_MAX}MB${NC} (${CYAN}${ALL_MAX_PERCENT}%${NC} of ${TOTAL_RAM_MB}MB)"
|
|
cecho " Status: ${CYAN}CAUTION - Monitor memory usage${NC}"
|
|
else
|
|
cecho " Total if all at max: ${GREEN}${TOTAL_CURRENT_MEMORY_WITH_MAX}MB${NC} (${GREEN}${ALL_MAX_PERCENT}%${NC} of ${TOTAL_RAM_MB}MB)"
|
|
cecho " Status: ${GREEN}${BOLD}HEALTHY${NC} - Sufficient memory headroom"
|
|
fi
|
|
echo ""
|
|
|
|
if [ "$OPTIMIZATION_COUNT" -gt 0 ]; then
|
|
cecho " ${BOLD}Recommendation:${NC}"
|
|
cecho " ${YELLOW}⚠ $OPTIMIZATION_COUNT domain(s) could be optimized${NC}"
|
|
cecho " Run: ${WHITE}php-optimizer.sh${NC} → ${CYAN}Option 5${NC} (Optimize Server-Wide)"
|
|
else
|
|
cecho " ${BOLD}Status:${NC}"
|
|
cecho " ${GREEN}✓ All domains are already optimized${NC}"
|
|
fi
|
|
|
|
echo ""
|
|
cecho "${CYAN}═════════════════════════════════════════════════════════════════════${NC}"
|
|
echo ""
|
|
|
|
# ============================================================================
|
|
# SAFETY WARNINGS
|
|
# ============================================================================
|
|
|
|
# Check memory headroom
|
|
AVAILABLE_AFTER_RECOMMENDED=$((TOTAL_RAM_MB - TOTAL_RECOMMENDED_MEMORY))
|
|
if [ "$AVAILABLE_AFTER_RECOMMENDED" -lt 2048 ]; then
|
|
cecho "${RED}${BOLD}⚠ WARNING: Limited memory headroom${NC}"
|
|
cecho " After applying recommended settings, only ${AVAILABLE_AFTER_RECOMMENDED}MB would be available"
|
|
echo ""
|
|
fi
|
|
|
|
# Check if already optimized
|
|
if [ "$OPTIMIZATION_COUNT" -eq 0 ]; then
|
|
cecho "${GREEN}${BOLD}✓ All domains are already optimized${NC}"
|
|
echo ""
|
|
fi
|
|
|
|
# ============================================================================
|
|
# CLEANUP
|
|
# ============================================================================
|
|
|
|
cecho "${WHITE}${BOLD}Report complete${NC}"
|
|
cecho " Generated: $(date '+%Y-%m-%d %H:%M:%S')"
|
|
echo ""
|
|
|
|
# Ask if user wants to save report
|
|
echo ""
|
|
cecho "${CYAN}─────────────────────────────────────────────────────────────────────${NC}"
|
|
read -p "Save detailed report to file? (y/n): " save_report
|
|
echo ""
|
|
|
|
REPORT_FILE="/tmp/php-fpm-analysis-$(date +%Y%m%d-%H%M%S).txt"
|
|
|
|
if [[ "$save_report" =~ ^[yY]$ ]] && [ -w /tmp ]; then
|
|
{
|
|
echo "╔════════════════════════════════════════════════════════════════════════╗"
|
|
echo "║ PHP-FPM BATCH ANALYSIS REPORT ║"
|
|
echo "╚════════════════════════════════════════════════════════════════════════╝"
|
|
echo ""
|
|
echo "REPORT GENERATED: $(date '+%Y-%m-%d %H:%M:%S')"
|
|
echo ""
|
|
echo "═══════════════════════════════════════════════════════════════════════════"
|
|
echo "SERVER INFORMATION"
|
|
echo "═══════════════════════════════════════════════════════════════════════════"
|
|
echo "Total RAM: ${TOTAL_RAM_MB}MB"
|
|
echo "CPU Cores: ${CPU_CORES}"
|
|
echo "Control Panel: ${CONTROL_PANEL}"
|
|
echo ""
|
|
|
|
echo "═══════════════════════════════════════════════════════════════════════════"
|
|
echo "DOMAIN-BY-DOMAIN ANALYSIS"
|
|
echo "═══════════════════════════════════════════════════════════════════════════"
|
|
echo ""
|
|
|
|
# Output domain details
|
|
for idx in $(seq 1 $TOTAL_DOMAINS); do
|
|
domain="${domain_list[$idx]}"
|
|
owner="${domain_owner[$idx]}"
|
|
current="${current_max_children[$idx]}"
|
|
recommended="${recommended_max_children[$idx]}"
|
|
impact="${memory_impact[$idx]}"
|
|
peak="${peak_concurrent[$idx]}"
|
|
|
|
if [ "$current" == "ERROR" ]; then
|
|
continue
|
|
fi
|
|
|
|
echo "[$idx] $domain"
|
|
echo " Owner: $owner"
|
|
echo " Peak concurrent requests: $peak"
|
|
echo " Current max_children: $current"
|
|
echo " Recommended max_children: $recommended"
|
|
echo " Memory impact: ${impact}MB"
|
|
echo ""
|
|
done
|
|
|
|
echo "═══════════════════════════════════════════════════════════════════════════"
|
|
echo "SUMMARY"
|
|
echo "═══════════════════════════════════════════════════════════════════════════"
|
|
echo ""
|
|
echo "Total domains analyzed: $TOTAL_DOMAINS"
|
|
echo "Domains needing optimization: $OPTIMIZATION_COUNT"
|
|
echo "Domains already optimized: $((TOTAL_DOMAINS - OPTIMIZATION_COUNT))"
|
|
echo ""
|
|
echo "Current memory allocation: ${TOTAL_CURRENT_MEMORY}MB (${CURRENT_PERCENT}% of RAM)"
|
|
echo "Recommended memory allocation: ${TOTAL_RECOMMENDED_MEMORY}MB (${RECOMMENDED_PERCENT}% of RAM)"
|
|
echo "Potential savings: ${POTENTIAL_SAVINGS}MB (${POTENTIAL_SAVINGS_PERCENT}% reduction)"
|
|
echo ""
|
|
echo "Memory available after optimization: $((TOTAL_RAM_MB - TOTAL_RECOMMENDED_MEMORY))MB"
|
|
echo ""
|
|
|
|
echo "═══════════════════════════════════════════════════════════════════════════"
|
|
echo "RECOMMENDATIONS"
|
|
echo "═══════════════════════════════════════════════════════════════════════════"
|
|
echo ""
|
|
|
|
if [ "$OPTIMIZATION_COUNT" -gt 0 ]; then
|
|
echo "Action: Optimize $OPTIMIZATION_COUNT domain(s)"
|
|
echo "Run: php-optimizer.sh → Option 5 (Optimize Server-Wide PHP Settings)"
|
|
echo "Expected outcome: Free up ${POTENTIAL_SAVINGS}MB of RAM"
|
|
else
|
|
echo "Status: All domains are already optimally configured"
|
|
echo "No optimization needed at this time"
|
|
fi
|
|
|
|
if [ "$(echo "$AVAILABLE_AFTER_RECOMMENDED < 2048" | bc)" -eq 1 ] 2>/dev/null; then
|
|
echo ""
|
|
echo "WARNING: Memory headroom after optimization is limited (${AVAILABLE_AFTER_RECOMMENDED}MB)"
|
|
echo "Consider reducing some domain limits further or upgrading server RAM"
|
|
fi
|
|
|
|
} > "$REPORT_FILE"
|
|
|
|
cecho "${GREEN}✓${NC} Detailed report saved to: ${CYAN}$REPORT_FILE${NC}"
|
|
echo ""
|
|
fi
|
|
|
|
echo ""
|