Add intelligent server-wide PHP optimization (option 5)

NEW FEATURE: Optimize Server-Wide PHP Settings

This implements the missing menu option 5 with intelligent, RAM-aware optimization
that analyzes the ENTIRE server before making any changes.

INTELLIGENT OPTIMIZATION PROCESS:

Step 1: Server Memory Capacity Analysis
- Calculates total RAM vs current max capacity across all pools
- Shows status: HEALTHY, CAUTION, WARNING, or CRITICAL
- Identifies if server is at risk of OOM

Step 2: Balanced Memory Allocation
- Uses calculate_balanced_memory_allocation() from php-analyzer.sh
- Distributes available RAM proportionally based on traffic
- Ensures total allocations never exceed physical RAM
- Accounts for system overhead (reserves 2GB or 20% of RAM)

Step 3: Smart Recommendations
- Shows BEFORE/AFTER values for each user
- Displays reason: REDUCE (prevent OOM), INCREASE (traffic demands), or OPTIMAL
- Requires explicit "yes" confirmation before applying

Step 4: Batch Optimization
- Applies pm.max_children settings for all users
- Tracks: OPcache disabled domains (manual intervention needed)
- Shows real-time progress per domain
- Automatic PHP-FPM reload after changes

FEATURES:

✓ Prevents OOM: Never allocates more RAM than physically available
✓ Traffic-aware: High-traffic sites get more resources
✓ Safe defaults: Minimum 5, maximum 200 processes per pool
✓ Progress tracking: Shows optimization status for each domain
✓ Summary report: Total optimized, skipped, detected issues
✓ Automatic restart: Reloads PHP-FPM services after changes

EXAMPLE OUTPUT:

Analyzing server capacity...
  Total RAM: 16384MB
  Current max capacity: 14200MB (86%)
  Status: CAUTION - Approaching memory limits

Calculating balanced optimization...
  user1: 50 → 35 (REDUCE - prevent OOM)
  user2: 20 → 45 (INCREASE - traffic demands)
  user3: 30 → 30 (OPTIMAL)

Apply these balanced optimizations? (yes/no): yes

[1] Processing: example.com [user1]
    ✓ Optimized (1 changes): max_children: 50→35

OPTIMIZATION SUMMARY
  Total domains processed: 25
  Optimized: 18
  Skipped (healthy): 7

  Changes applied:
    • max_children: 18 domains
    • opcache_needs_enable: 5 domains
This commit is contained in:
cschantz
2025-12-11 21:53:05 -05:00
parent 842b71a909
commit fb300bb364
+238 -2
View File
@@ -567,6 +567,243 @@ optimize_domain() {
read -p "Press Enter to continue..."
}
# ============================================================================
# OPTIMIZE ALL DOMAINS (SERVER-WIDE)
# ============================================================================
optimize_all_domains() {
show_banner
cecho "${WHITE}${BOLD}SERVER-WIDE OPTIMIZATION${NC}"
echo ""
cecho "${YELLOW}This will analyze and optimize PHP settings for ALL domains on the server.${NC}"
echo ""
cecho "${CYAN}What will be optimized:${NC}"
cecho " • pm.max_children (based on memory analysis)"
cecho " • OPcache settings (enable if disabled)"
echo ""
cecho "${RED}${BOLD}WARNING:${NC} ${RED}This will modify PHP-FPM pool configurations server-wide!${NC}"
echo ""
read -p "Continue with server-wide optimization? (yes/no): " confirm
if [ "$confirm" != "yes" ]; then
cecho "${YELLOW}Operation cancelled${NC}"
read -p "Press Enter to continue..."
return
fi
show_banner
cecho "${WHITE}${BOLD}Analyzing server capacity...${NC}"
echo ""
# First: Calculate server-wide memory capacity
cecho "${CYAN}Step 1: Checking server memory capacity...${NC}"
local capacity_result
capacity_result=$(calculate_server_memory_capacity 2>&1)
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 ""
cecho " Total RAM: ${WHITE}${total_ram_mb}MB${NC}"
cecho " Current max capacity: ${WHITE}${total_required_mb}MB${NC} (${percentage}%)"
case "$status" in
CRITICAL)
cecho " Status: ${RED}${BOLD}CRITICAL${NC} - Server may OOM if all pools hit max!"
;;
WARNING)
cecho " Status: ${YELLOW}${BOLD}WARNING${NC} - High memory pressure possible"
;;
CAUTION)
cecho " Status: ${YELLOW}CAUTION${NC} - Approaching memory limits"
;;
HEALTHY)
cecho " Status: ${GREEN}HEALTHY${NC} - Sufficient headroom"
;;
esac
echo ""
cecho "${CYAN}Step 2: Calculating balanced optimization...${NC}"
echo ""
# Get balanced recommendations based on total RAM
local balanced_result
balanced_result=$(calculate_balanced_memory_allocation 2>&1)
# Parse recommendations (format: USER|CURRENT_MAX|AVG_MB|TRAFFIC_RPM|RECOMMENDED_MAX|ALLOCATED_MB|REASON)
declare -A recommended_values
while IFS='|' read -r username current_max avg_mb traffic_rpm recommended_max allocated_mb reason; do
[ "$username" = "USER" ] && continue # Skip header
[ -z "$username" ] && continue
recommended_values["$username"]="$recommended_max"
cecho " ${CYAN}$username${NC}: $current_max$recommended_max (${reason})"
done <<< "$balanced_result"
echo ""
read -p "Apply these balanced optimizations? (yes/no): " apply_confirm
if [ "$apply_confirm" != "yes" ]; then
cecho "${YELLOW}Optimization cancelled${NC}"
read -p "Press Enter to continue..."
return
fi
show_banner
cecho "${WHITE}${BOLD}Applying optimizations...${NC}"
echo ""
# Get all users
local users
users=$(list_all_users)
if [ -z "$users" ]; then
cecho "${RED}ERROR: No users found on system${NC}"
read -p "Press Enter to continue..."
return
fi
# Statistics tracking
local total_domains=0
local optimized_count=0
local skipped_count=0
declare -A optimization_summary
# Process each user
while IFS= read -r username; do
[ -z "$username" ] && continue
local user_domains
user_domains=$(get_user_domains "$username")
while IFS= read -r domain; do
[ -z "$domain" ] && continue
total_domains=$((total_domains + 1))
cecho "${CYAN}[$total_domains] Processing: ${WHITE}$domain${NC} ${CYAN}[$username]${NC}"
# Detect issues first
local issues
issues=$(detect_php_config_issues "$username" "$domain")
# Count critical/high issues
local critical_high_count
critical_high_count=$(echo "$issues" | grep -cE "^[^|]*\|(CRITICAL|HIGH)\|" || true)
if [ "$critical_high_count" -eq 0 ]; then
cecho " ${GREEN}${NC} No optimization needed - domain is healthy"
skipped_count=$((skipped_count + 1))
continue
fi
# Use balanced recommendation from server-wide analysis
local recommended_max_children
recommended_max_children="${recommended_values[$username]}"
# If no recommendation found, skip
if [ -z "$recommended_max_children" ]; then
continue
fi
# Get current pool config
local pool_config
pool_config=$(find_fpm_pool_config "$username")
if [ -z "$pool_config" ] || [ ! -f "$pool_config" ]; then
cecho " ${YELLOW}${NC} No FPM pool config found - skipping"
skipped_count=$((skipped_count + 1))
continue
fi
# Get current max_children
local current_max_children
current_max_children=$(grep "^pm.max_children" "$pool_config" | awk -F'=' '{print $2}' | tr -d ' ')
# Apply optimizations
local changes_made=0
local changes_list=""
# Optimization 1: Adjust max_children if needed
if [ -n "$recommended_max_children" ] && [ -n "$current_max_children" ] && [ "$recommended_max_children" -ne "$current_max_children" ]; then
if modify_fpm_pool_setting "$pool_config" "pm.max_children" "$recommended_max_children" >/dev/null 2>&1; then
changes_made=$((changes_made + 1))
changes_list+="max_children: $current_max_children$recommended_max_children, "
optimization_summary["max_children"]=$((${optimization_summary["max_children"]:-0} + 1))
fi
fi
# Optimization 2: Enable OPcache if disabled
local opcache_enabled
opcache_enabled=$(check_opcache_enabled "$username")
if [ "$opcache_enabled" = "0" ]; then
# OPcache is disabled - mark for enabling (note: requires php.ini edit, not implemented yet)
changes_list+="OPcache: needs_enable, "
optimization_summary["opcache_needs_enable"]=$((${optimization_summary["opcache_needs_enable"]:-0} + 1))
fi
# Remove trailing comma
changes_list=${changes_list%, }
if [ "$changes_made" -gt 0 ]; then
cecho " ${GREEN}${NC} Optimized ($changes_made changes): $changes_list"
optimized_count=$((optimized_count + 1))
else
if [ -n "$changes_list" ]; then
cecho " ${YELLOW}${NC} Detected: $changes_list (manual intervention needed)"
skipped_count=$((skipped_count + 1))
else
cecho " ${YELLOW}${NC} No changes applied"
skipped_count=$((skipped_count + 1))
fi
fi
done <<< "$user_domains"
done <<< "$users"
# Restart PHP-FPM services if changes were made
if [ "$optimized_count" -gt 0 ]; then
echo ""
cecho "${CYAN}Restarting PHP-FPM services...${NC}"
# Get all PHP versions
local php_versions
php_versions=$(detect_installed_php_versions)
while IFS= read -r php_version; do
[ -z "$php_version" ] && continue
if reload_php_fpm "$php_version" >/dev/null 2>&1; then
cecho " ${GREEN}${NC} Reloaded $php_version"
fi
done <<< "$php_versions"
fi
# Display summary
echo ""
cecho "${CYAN}═══════════════════════════════════════════════════════════════════${NC}"
cecho "${WHITE}${BOLD}OPTIMIZATION SUMMARY${NC}"
cecho "${CYAN}═══════════════════════════════════════════════════════════════════${NC}"
echo ""
cecho " Total domains processed: ${WHITE}$total_domains${NC}"
cecho " ${GREEN}Optimized: $optimized_count${NC}"
cecho " ${YELLOW}Skipped (healthy): $skipped_count${NC}"
echo ""
if [ ${#optimization_summary[@]} -gt 0 ]; then
cecho "${WHITE}Changes applied:${NC}"
for key in "${!optimization_summary[@]}"; do
cecho "$key: ${optimization_summary[$key]} domains"
done
fi
echo ""
cecho "${CYAN}═══════════════════════════════════════════════════════════════════${NC}"
echo ""
read -p "Press Enter to continue..."
}
# ============================================================================
# OPTION 6: VIEW OPCACHE STATISTICS
# ============================================================================
@@ -1178,8 +1415,7 @@ main() {
optimize_domain
;;
5)
cecho "${YELLOW}Server-wide optimization not yet implemented${NC}"
sleep 2
optimize_all_domains
;;
6)
view_opcache_stats