diff --git a/lib/php-calculator-improved.sh b/lib/php-calculator-improved.sh index f8e2b34..0bc73c4 100644 --- a/lib/php-calculator-improved.sh +++ b/lib/php-calculator-improved.sh @@ -105,30 +105,47 @@ calculate_max_children_memory_based() { local reserved_mb reserved_mb=$(get_field "$reserve_result" 1) - # Available memory for PHP-FPM - local available_mb=$((total_ram_mb - reserved_mb)) + # Account for MySQL memory (critical on shared hosting!) + local mysql_memory_mb=0 + local mysql_info + mysql_info=$(detect_mysql_memory_usage 2>/dev/null) + if [ $? -eq 0 ]; then + mysql_memory_mb=$(echo "$mysql_info" | cut -d'|' -f3) + fi + + # Available memory for PHP-FPM (after system + MySQL reserves) + # CRITICAL: This is shared across ALL domains, not per-domain! + local available_mb=$((total_ram_mb - reserved_mb - mysql_memory_mb)) + + # Safety check: never allow PHP-FPM to use more than 60% of RAM + local max_php_fpm=$((total_ram_mb * 60 / 100)) + if [ "$available_mb" -gt "$max_php_fpm" ]; then + available_mb=$max_php_fpm + fi # Convert average KB to MB local avg_mb=$((avg_kb / 1024)) if [ "$avg_mb" -eq 0 ]; then - avg_mb=1 # Minimum 1MB to prevent division issues + avg_mb=20 # More realistic default (not 1MB) fi # Theoretical maximum without safety buffer local theoretical_max=$((available_mb / avg_mb)) - # Apply safety buffer (default 15%, refined later based on traffic patterns) - local safety_buffer=15 + # Apply safety buffer (50% - much more conservative for shared hosting!) + # This accounts for peak traffic spikes and other processes + local safety_buffer=50 local recommended=$((theoretical_max * (100 - safety_buffer) / 100)) - # Sanity checks - if [ "$recommended" -lt 2 ]; then - echo "2|Minimum safe value (insufficient memory)" - elif [ "$recommended" -gt 500 ]; then - # Cap at 500 (typical proxy upstream pool size) - echo "500|Capped at safe maximum (would be $recommended)" + # Hard cap at traffic-realistic limits + if [ "$recommended" -lt 5 ]; then + echo "5|Minimum safe value (insufficient memory)" + elif [ "$recommended" -gt 150 ]; then + # CRITICAL: Cap at 150 max per domain on shared hosting + # Higher values require dedicated servers + echo "150|Capped at safe maximum for shared hosting (would be $recommended)" else - local reason="Memory-based: ${avg_mb}MB per process, ${available_mb}MB available, ${safety_buffer}% buffer" + local reason="Memory-based: ${avg_mb}MB per process, ${available_mb}MB available (after MySQL: ${mysql_memory_mb}MB), ${safety_buffer}% safety buffer" echo "$recommended|$reason" fi } diff --git a/modules/performance/php-optimizer.sh b/modules/performance/php-optimizer.sh index 857ee4c..54c46f5 100755 --- a/modules/performance/php-optimizer.sh +++ b/modules/performance/php-optimizer.sh @@ -2448,6 +2448,17 @@ optimize_level_5_everything() { cecho " Status: ${WHITE}${status}${NC}" echo "" + # CRITICAL SAFETY CHECK: If current usage is already > 80%, warn user + if [ "$percentage" -gt 80 ]; then + cecho "${RED}${BOLD}⚠ CRITICAL: Server is running with insufficient PHP-FPM headroom!${NC}" + cecho "${RED}Current allocation is ${percentage}% of RAM.${NC}" + cecho "${RED}Optimization may not be sufficient - consider:${NC}" + cecho "${RED} 1. Upgrading server RAM${NC}" + cecho "${RED} 2. Disabling problematic domains${NC}" + cecho "${RED} 3. Migrating heavy sites to dedicated servers${NC}" + echo "" + fi + cecho "${CYAN}STEP 2: Calculating Recommendations${NC}" echo "" @@ -2531,6 +2542,50 @@ optimize_level_5_everything() { cecho " Domains needing OPcache: ${YELLOW}${opcache_count}${NC}" echo "" + # CRITICAL VALIDATION: Check if combined recommendations exceed safe limits + cecho "${CYAN}STEP 2b: Validating Combined Capacity${NC}" + echo "" + + local total_recommended_max_children=0 + local avg_memory_per_process=20 # Conservative 20MB per process + local total_recommended_memory=0 + + for domain in "${!recommended_max_children[@]}"; do + local rec_max="${recommended_max_children[$domain]}" + [ -z "$rec_max" ] && continue + total_recommended_max_children=$((total_recommended_max_children + rec_max)) + total_recommended_memory=$((total_recommended_memory + (rec_max * avg_memory_per_process))) + done + + # Determine if recommendations are safe + local max_safe_php_fpm=$((total_ram_mb * 60 / 100)) # 60% of RAM for PHP-FPM + + if [ "$total_recommended_memory" -gt "$max_safe_php_fpm" ]; then + cecho "${RED}${BOLD}⚠ WARNING: Combined recommendations exceed safe limits!${NC}" + cecho "${RED}Recommended total: ${total_recommended_memory}MB (${total_recommended_max_children} max_children combined)${NC}" + cecho "${RED}Safe maximum: ${max_safe_php_fpm}MB${NC}" + cecho "${YELLOW}Applying safety caps to prevent OOM crashes...${NC}" + + # Scale down all recommendations proportionally + local scale_factor=$((max_safe_php_fpm * 100 / total_recommended_memory)) + scale_factor=$((scale_factor / 100)) # Convert to percentage + + for domain in "${!recommended_max_children[@]}"; do + local old_max="${recommended_max_children[$domain]}" + [ -z "$old_max" ] && continue + local new_max=$((old_max * scale_factor / 100)) + [ "$new_max" -lt 5 ] && new_max=5 + [ "$new_max" -gt 150 ] && new_max=150 # Hard cap for shared hosting + recommended_max_children["$domain"]="$new_max" + done + + echo "" + cecho "${GREEN}✓ Safety caps applied${NC}" + else + cecho "${GREEN}✓ Combined capacity is safe: ${total_recommended_memory}MB (${total_recommended_max_children} total max_children)${NC}" + fi + echo "" + cecho "${CYAN}STEP 3: Applying All Optimizations${NC}" echo ""