Compare commits
6 Commits
94c486717f
...
c90f7155ce
| Author | SHA1 | Date | |
|---|---|---|---|
| c90f7155ce | |||
| ba6848e113 | |||
| 3a14df27ae | |||
| 746b861640 | |||
| 333bc756ec | |||
| 0f4ea3ff9b |
@@ -413,69 +413,38 @@ get_domain_traffic_percentage() {
|
|||||||
domain_count=$(echo "$all_domains" | grep -v "^$" | wc -l)
|
domain_count=$(echo "$all_domains" | grep -v "^$" | wc -l)
|
||||||
[ "$domain_count" -lt 1 ] && domain_count=1
|
[ "$domain_count" -lt 1 ] && domain_count=1
|
||||||
|
|
||||||
# SIMPLIFIED APPROACH: Use equal distribution by default
|
# CRITICAL FIX: Use peak concurrent to estimate traffic percentage
|
||||||
# (Advanced traffic analysis requires domain-specific access logs which are control-panel dependent)
|
# (Access log parsing is unreliable across control panels)
|
||||||
local equal_share=$((100 / domain_count))
|
# Peak concurrent is a reliable indicator of traffic intensity
|
||||||
|
|
||||||
# Try to find domain-specific access log (best effort, not required)
|
# Get this domain's peak concurrent
|
||||||
# This varies by control panel:
|
local domain_peak
|
||||||
# - cPanel: /var/log/apache2/domlogs/DOMAIN or /home/user/logs/DOMAIN-access_log
|
domain_peak=$(get_domain_peak_concurrent "$domain" 2>/dev/null || echo "0")
|
||||||
# - Plesk: /var/www/vhosts/DOMAIN/logs/access_log
|
[ -z "$domain_peak" ] && domain_peak=0
|
||||||
# - InterWorx: /home/user/var/DOMAIN/logs/transfer.log
|
|
||||||
|
|
||||||
local domain_requests=0
|
# Calculate total peak concurrent across ALL domains
|
||||||
local total_requests=0
|
local total_peak=0
|
||||||
|
local domain_check
|
||||||
|
while IFS= read -r domain_check; do
|
||||||
|
[ -z "$domain_check" ] && continue
|
||||||
|
local peak_val
|
||||||
|
peak_val=$(get_domain_peak_concurrent "$domain_check" 2>/dev/null || echo "0")
|
||||||
|
[ -z "$peak_val" ] && peak_val=0
|
||||||
|
total_peak=$((total_peak + peak_val))
|
||||||
|
done <<< "$all_domains"
|
||||||
|
|
||||||
# Best-effort search for domain access log
|
# Calculate percentage based on peak concurrent
|
||||||
local access_log
|
if [ "$total_peak" -gt 0 ]; then
|
||||||
access_log=$(find /var/log/apache2/domlogs -name "*$domain*" -type f 2>/dev/null | head -1)
|
local percentage=$((domain_peak * 100 / total_peak))
|
||||||
|
[ "$percentage" -lt 1 ] && percentage=1
|
||||||
if [ -z "$access_log" ]; then
|
[ "$percentage" -gt 99 ] && percentage=99
|
||||||
access_log=$(find /var/www/vhosts -name "access_log" -path "*$domain*" -type f 2>/dev/null | head -1)
|
echo "$percentage|$domain_peak|Based on peak concurrent (traffic intensity)"
|
||||||
fi
|
return
|
||||||
|
|
||||||
if [ -z "$access_log" ]; then
|
|
||||||
access_log=$(find /home -name "transfer.log" -path "*$domain*" -type f 2>/dev/null | head -1)
|
|
||||||
fi
|
|
||||||
|
|
||||||
# If we found a domain-specific log, try to calculate percentage
|
|
||||||
if [ -n "$access_log" ] && [ -f "$access_log" ]; then
|
|
||||||
# Count lines in this domain's access log
|
|
||||||
domain_requests=$(tail -n 100000 "$access_log" 2>/dev/null | wc -l)
|
|
||||||
|
|
||||||
# Only use calculated percentage if we have significant data
|
|
||||||
if [ "$domain_requests" -gt 10 ]; then
|
|
||||||
# IMPROVED: Try to sum requests from multiple domain logs (not just 2)
|
|
||||||
# This is more accurate for multi-domain servers
|
|
||||||
total_requests=0
|
|
||||||
local log_count=0
|
|
||||||
|
|
||||||
# Find all domain logs in the same location as our domain log
|
|
||||||
local log_dir
|
|
||||||
log_dir=$(dirname "$access_log")
|
|
||||||
|
|
||||||
# Count requests from all logs in this directory
|
|
||||||
while IFS= read -r log; do
|
|
||||||
[ -f "$log" ] || continue
|
|
||||||
local log_requests
|
|
||||||
log_requests=$(tail -n 100000 "$log" 2>/dev/null | wc -l)
|
|
||||||
total_requests=$((total_requests + log_requests))
|
|
||||||
log_count=$((log_count + 1))
|
|
||||||
done < <(find "$log_dir" -maxdepth 1 -type f -name "*" 2>/dev/null | head -20)
|
|
||||||
|
|
||||||
# Only calculate percentage if we found at least 2 logs
|
|
||||||
if [ "$log_count" -ge 2 ] && [ "$total_requests" -gt 0 ]; then
|
|
||||||
local percentage=$((domain_requests * 100 / total_requests))
|
|
||||||
[ "$percentage" -lt 1 ] && percentage=1
|
|
||||||
[ "$percentage" -gt 99 ] && percentage=99
|
|
||||||
echo "$percentage|$domain_requests|Based on $log_count domain logs"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Fallback: equal distribution among all domains
|
# Fallback: equal distribution among all domains
|
||||||
# This is the SAFEST approach when we can't reliably calculate percentages
|
# This is the SAFEST approach when we can't calculate percentages
|
||||||
|
local equal_share=$((100 / domain_count))
|
||||||
echo "$equal_share|0|Using equal distribution ($domain_count domains) - safest assumption"
|
echo "$equal_share|0|Using equal distribution ($domain_count domains) - safest assumption"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+40
-23
@@ -412,14 +412,18 @@ get_domain_peak_concurrent() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Analyze access log for peak concurrent requests (simplified)
|
# Analyze access log for peak concurrent requests
|
||||||
|
# Apache logs: timestamp is [DD/Mon/YYYY:HH:MM:SS]
|
||||||
|
# Extract HH:MM (hour and minute) for minute-level granularity
|
||||||
|
# Count requests per minute, estimate concurrent = requests/min * avg_duration / 60
|
||||||
|
# Assumption: average PHP request takes ~1-2 seconds (multiplier 0.15)
|
||||||
tail -100000 "$log_file" 2>/dev/null | \
|
tail -100000 "$log_file" 2>/dev/null | \
|
||||||
awk '{print $4}' | \
|
awk '{print $4}' | \
|
||||||
sed 's/\[//' | \
|
sed 's/\[//; s/\].*//' | \
|
||||||
awk -F: '{print $3}' | \
|
awk -F: '{print $2 ":" $3}' | \
|
||||||
sort | uniq -c | \
|
sort | uniq -c | \
|
||||||
sort -rn | head -1 | \
|
sort -rn | head -1 | \
|
||||||
awk '{print $1}' || echo "0"
|
awk '{requests=$1; concurrent = int(requests * 0.15); if (concurrent < 1) concurrent = (requests > 0 ? 1 : 0); print concurrent}' || echo "0"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check if a domain is already optimized
|
# Check if a domain is already optimized
|
||||||
@@ -479,34 +483,47 @@ find_domain_access_log() {
|
|||||||
|
|
||||||
case "${SYS_CONTROL_PANEL:-unknown}" in
|
case "${SYS_CONTROL_PANEL:-unknown}" in
|
||||||
cpanel)
|
cpanel)
|
||||||
local owner
|
# cPanel standard locations for access logs
|
||||||
owner=$(find_domain_owner "$domain")
|
# Primary: /var/log/apache2/domlogs/DOMAIN (or DOMAIN-error_log, etc)
|
||||||
if [ -n "$owner" ]; then
|
# Secondary: /home/USER/access-logs/ (symlink to above)
|
||||||
# Try access-logs directory first (follows symlinks)
|
local log_file
|
||||||
local log_file
|
|
||||||
log_file=$(find -L "/home/${owner}/access-logs" -type f -name "*${domain}*" 2>/dev/null | head -1)
|
|
||||||
|
|
||||||
# If not found, try Apache domlogs directory directly
|
# Try standard cPanel domlogs directory FIRST (primary location)
|
||||||
if [ -z "$log_file" ] && [ -d "/etc/apache2/logs/domlogs" ]; then
|
log_file=$(find "/var/log/apache2/domlogs" -maxdepth 1 -type f -name "*${domain}*" 2>/dev/null | head -1)
|
||||||
log_file=$(find "/etc/apache2/logs/domlogs" -type f -name "*${domain}*" 2>/dev/null | head -1)
|
|
||||||
|
# If not found, try user's access-logs directory (symlink, follows)
|
||||||
|
if [ -z "$log_file" ]; then
|
||||||
|
local owner
|
||||||
|
owner=$(find_domain_owner "$domain")
|
||||||
|
if [ -n "$owner" ] && [ -d "/home/${owner}/access-logs" ]; then
|
||||||
|
log_file=$(find -L "/home/${owner}/access-logs" -maxdepth 1 -type f -name "*${domain}*" 2>/dev/null | head -1)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# If not found, try public_html
|
|
||||||
if [ -z "$log_file" ] && [ -d "/home/${owner}/public_html" ]; then
|
|
||||||
log_file=$(find "/home/${owner}/public_html" -maxdepth 2 -type f -name "access_log*" 2>/dev/null | head -1)
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "$log_file"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Try alternative cPanel path
|
||||||
|
if [ -z "$log_file" ] && [ -d "/etc/apache2/logs/domlogs" ]; then
|
||||||
|
log_file=$(find "/etc/apache2/logs/domlogs" -maxdepth 1 -type f -name "*${domain}*" 2>/dev/null | head -1)
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$log_file"
|
||||||
;;
|
;;
|
||||||
plesk)
|
plesk)
|
||||||
find "/var/www/vhosts/${domain}/statistics/logs" -type f -name "access_log*" 2>/dev/null | head -1
|
# Plesk standard locations
|
||||||
|
# Format varies: /var/www/vhosts/DOMAIN/logs/ or /var/www/vhosts/system/DOMAIN/logs/
|
||||||
|
find "/var/www/vhosts" -path "*/logs/*" -name "*access*" -o -path "*/system/${domain}/logs/*" 2>/dev/null | head -1
|
||||||
;;
|
;;
|
||||||
interworx)
|
interworx)
|
||||||
find "/home/*/public_html/${domain}" -type f -name "access_log*" 2>/dev/null | head -1
|
# InterWorx standard location: /home/USER/var/DOMAIN/logs/
|
||||||
|
find "/home/*/var/${domain}/logs" -type f -name "*access*" 2>/dev/null | head -1
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
find /var/log -type f -name "*${domain}*access*log*" 2>/dev/null | head -1
|
# Standalone/unknown - search common locations
|
||||||
|
local log_file
|
||||||
|
log_file=$(find "/var/log/apache2/domlogs" -maxdepth 1 -type f -name "*${domain}*" 2>/dev/null | head -1)
|
||||||
|
if [ -z "$log_file" ]; then
|
||||||
|
log_file=$(find "/var/log" -maxdepth 2 -type f -name "*${domain}*access*" 2>/dev/null | head -1)
|
||||||
|
fi
|
||||||
|
echo "$log_file"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -280,17 +280,18 @@ for idx in "${sorted_indices[@]}"; do
|
|||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Determine traffic indicator
|
# Determine traffic indicator based on traffic PERCENTAGE (not peak concurrent)
|
||||||
traffic_indicator=""
|
traffic_indicator=""
|
||||||
if [[ "$peak" =~ ^[0-9]+$ ]]; then
|
traffic_pct="${traffic_percentage_arr[$idx]:-0}"
|
||||||
if [ "$peak" -ge 20 ]; then
|
if [[ "$traffic_pct" =~ ^[0-9]+$ ]]; then
|
||||||
traffic_indicator="${RED}⚠ CRITICAL TRAFFIC (${peak})${NC}"
|
if [ "$traffic_pct" -ge 50 ]; then
|
||||||
elif [ "$peak" -ge 10 ]; then
|
traffic_indicator="${RED}⚠ CRITICAL TRAFFIC${NC}"
|
||||||
traffic_indicator="${YELLOW}⚠ HIGH TRAFFIC (${peak})${NC}"
|
elif [ "$traffic_pct" -ge 25 ]; then
|
||||||
elif [ "$peak" -ge 5 ]; then
|
traffic_indicator="${YELLOW}⚠ HIGH TRAFFIC${NC}"
|
||||||
traffic_indicator="${CYAN}→ MEDIUM TRAFFIC (${peak})${NC}"
|
elif [ "$traffic_pct" -ge 10 ]; then
|
||||||
|
traffic_indicator="${CYAN}→ MEDIUM TRAFFIC${NC}"
|
||||||
else
|
else
|
||||||
traffic_indicator="${WHITE}○ LOW TRAFFIC (${peak})${NC}"
|
traffic_indicator="${WHITE}○ LOW TRAFFIC${NC}"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
traffic_indicator="${WHITE}○ TRAFFIC UNKNOWN${NC}"
|
traffic_indicator="${WHITE}○ TRAFFIC UNKNOWN${NC}"
|
||||||
@@ -317,7 +318,7 @@ for idx in "${sorted_indices[@]}"; do
|
|||||||
else
|
else
|
||||||
cecho "${GREEN}[$idx]${NC} $domain"
|
cecho "${GREEN}[$idx]${NC} $domain"
|
||||||
cecho " Owner: $owner"
|
cecho " Owner: $owner"
|
||||||
cecho " Traffic: $traffic_indicator"
|
cecho " Traffic: $traffic_indicator (${traffic_percentage_arr[$idx]}% of server)"
|
||||||
cecho ""
|
cecho ""
|
||||||
cecho " ${BOLD}Pool Settings:${NC}"
|
cecho " ${BOLD}Pool Settings:${NC}"
|
||||||
cecho " pm.max_children: $current"
|
cecho " pm.max_children: $current"
|
||||||
|
|||||||
@@ -1563,6 +1563,17 @@ optimize_level_1_max_children() {
|
|||||||
echo ""
|
echo ""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Calculate server capacity for intelligent three-constraint model
|
||||||
|
local server_capacity_result
|
||||||
|
server_capacity_result=$(calculate_server_capacity "$total_ram_mb")
|
||||||
|
local server_capacity
|
||||||
|
server_capacity=$(echo "$server_capacity_result" | cut -d'|' -f1)
|
||||||
|
local server_memory_per_process
|
||||||
|
server_memory_per_process=$(echo "$server_capacity_result" | cut -d'|' -f3)
|
||||||
|
cecho " Server PHP-FPM capacity: ${WHITE}${server_capacity}${NC} max_children"
|
||||||
|
cecho " Using intelligent three-constraint model: Memory + Traffic + Fair Share"
|
||||||
|
echo ""
|
||||||
|
|
||||||
# Get recommendations
|
# Get recommendations
|
||||||
cecho "${CYAN}Step 2: Calculating optimal settings...${NC}"
|
cecho "${CYAN}Step 2: Calculating optimal settings...${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
@@ -1575,6 +1586,18 @@ optimize_level_1_max_children() {
|
|||||||
local users
|
local users
|
||||||
users=$(list_all_users)
|
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=""
|
||||||
|
while IFS= read -r u; do
|
||||||
|
[ -z "$u" ] && continue
|
||||||
|
u_domains=$(get_user_domains "$u")
|
||||||
|
while IFS= read -r d; do
|
||||||
|
[ -z "$d" ] && continue
|
||||||
|
all_domains_string="$all_domains_string$d"$'\n'
|
||||||
|
done <<< "$u_domains"
|
||||||
|
done <<< "$users"
|
||||||
|
|
||||||
while IFS= read -r username; do
|
while IFS= read -r username; do
|
||||||
[ -z "$username" ] && continue
|
[ -z "$username" ] && continue
|
||||||
local user_domains
|
local user_domains
|
||||||
@@ -1594,16 +1617,21 @@ optimize_level_1_max_children() {
|
|||||||
current_max="?"
|
current_max="?"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Get recommendations - use profile if available, otherwise use traffic-based
|
# Get recommendations - use profile if available, otherwise use intelligent three-constraint model
|
||||||
local recommended_max
|
local recommended_max
|
||||||
if [ "$profiles_exist" = "1" ] && [ -f "/tmp/php-domain-profiles/$domain.profile" ]; then
|
if [ "$profiles_exist" = "1" ] && [ -f "/tmp/php-domain-profiles/$domain.profile" ]; then
|
||||||
recommended_max=$(get_max_children_recommendation "$domain" "$username")
|
recommended_max=$(get_max_children_recommendation "$domain" "$username")
|
||||||
else
|
else
|
||||||
# Fallback to traffic-based (old method)
|
# Use intelligent three-constraint model (same as Level 5)
|
||||||
local traffic_rpm
|
local traffic_pct
|
||||||
traffic_rpm=$(get_domain_peak_concurrent "$domain" 2>/dev/null || echo "0")
|
traffic_pct=$(get_domain_traffic_percentage "$username" "$domain" "$all_domains_string" 2>/dev/null | cut -d'|' -f1)
|
||||||
[ "$traffic_rpm" = "?" ] && traffic_rpm="0"
|
traffic_pct=${traffic_pct:-50}
|
||||||
recommended_max=$((traffic_rpm > 5 ? traffic_rpm + 10 : 5))
|
|
||||||
|
# Call intelligent three-constraint function
|
||||||
|
local intel_result
|
||||||
|
intel_result=$(calculate_optimal_php_settings_intelligent "$username" "$total_ram_mb" "$server_capacity" "$traffic_pct" 2>/dev/null || echo "20|dynamic|1|5|ERROR|Failed")
|
||||||
|
|
||||||
|
recommended_max=$(echo "$intel_result" | cut -d'|' -f1)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
recommended_values["$domain"]="$recommended_max"
|
recommended_values["$domain"]="$recommended_max"
|
||||||
@@ -1621,6 +1649,46 @@ optimize_level_1_max_children() {
|
|||||||
done <<< "$user_domains"
|
done <<< "$user_domains"
|
||||||
done <<< "$users"
|
done <<< "$users"
|
||||||
|
|
||||||
|
# CRITICAL VALIDATION: Check if combined recommendations exceed safe limits
|
||||||
|
cecho "${CYAN}Step 2b: Validating capacity...${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
local total_recommended_max_children=0
|
||||||
|
local avg_memory_per_process=$server_memory_per_process
|
||||||
|
local total_recommended_memory=0
|
||||||
|
|
||||||
|
for domain in "${!recommended_values[@]}"; do
|
||||||
|
local rec_max="${recommended_values[$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))
|
||||||
|
|
||||||
|
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}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Scale down all recommendations proportionally
|
||||||
|
local scale_factor
|
||||||
|
scale_factor=$((max_safe_php_fpm * 100 / total_recommended_memory))
|
||||||
|
|
||||||
|
for domain in "${!recommended_values[@]}"; do
|
||||||
|
local rec_max="${recommended_values[$domain]}"
|
||||||
|
[ -z "$rec_max" ] && continue
|
||||||
|
rec_max=$((rec_max * scale_factor / 100))
|
||||||
|
[ "$rec_max" -lt 5 ] && rec_max=5
|
||||||
|
recommended_values["$domain"]="$rec_max"
|
||||||
|
done
|
||||||
|
cecho "${CYAN}Applied proportional scaling (${scale_factor}%)${NC}"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
if [ "$changes_needed" -eq 0 ]; then
|
if [ "$changes_needed" -eq 0 ]; then
|
||||||
cecho "${GREEN}${BOLD}✓ All domains already optimized - no changes needed${NC}"
|
cecho "${GREEN}${BOLD}✓ All domains already optimized - no changes needed${NC}"
|
||||||
@@ -1752,6 +1820,17 @@ optimize_level_2_memory() {
|
|||||||
cecho " Status: ${WHITE}${status}${NC}"
|
cecho " Status: ${WHITE}${status}${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
|
# Calculate server capacity for intelligent three-constraint model
|
||||||
|
local server_capacity_result
|
||||||
|
server_capacity_result=$(calculate_server_capacity "$total_ram_mb")
|
||||||
|
local server_capacity
|
||||||
|
server_capacity=$(echo "$server_capacity_result" | cut -d'|' -f1)
|
||||||
|
local server_memory_per_process
|
||||||
|
server_memory_per_process=$(echo "$server_capacity_result" | cut -d'|' -f3)
|
||||||
|
cecho " Server PHP-FPM capacity: ${WHITE}${server_capacity}${NC} max_children"
|
||||||
|
cecho " Using intelligent three-constraint model: Memory + Traffic + Fair Share"
|
||||||
|
echo ""
|
||||||
|
|
||||||
# Check if profiles exist
|
# Check if profiles exist
|
||||||
local profiles_exist=0
|
local profiles_exist=0
|
||||||
if [ -d "/tmp/php-domain-profiles" ] && [ "$(ls -1 /tmp/php-domain-profiles/*.profile 2>/dev/null | wc -l)" -gt 0 ]; then
|
if [ -d "/tmp/php-domain-profiles" ] && [ "$(ls -1 /tmp/php-domain-profiles/*.profile 2>/dev/null | wc -l)" -gt 0 ]; then
|
||||||
@@ -1762,7 +1841,7 @@ optimize_level_2_memory() {
|
|||||||
else
|
else
|
||||||
cecho "${YELLOW}${BOLD}⚠ No domain profiles found${NC}"
|
cecho "${YELLOW}${BOLD}⚠ No domain profiles found${NC}"
|
||||||
cecho "${CYAN}For more accurate optimization, run pre-analysis first:${NC}"
|
cecho "${CYAN}For more accurate optimization, run pre-analysis first:${NC}"
|
||||||
cecho " ${WHITE}php-optimizer.sh${NC} → Option 3 (Pre-analyze domains)"
|
cecho " ${WHITE}php-optimizer.sh${NC} → Option 0 (Pre-analyze domains)"
|
||||||
echo ""
|
echo ""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -1779,6 +1858,18 @@ optimize_level_2_memory() {
|
|||||||
local users
|
local users
|
||||||
users=$(list_all_users)
|
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=""
|
||||||
|
while IFS= read -r u; do
|
||||||
|
[ -z "$u" ] && continue
|
||||||
|
u_domains=$(get_user_domains "$u")
|
||||||
|
while IFS= read -r d; do
|
||||||
|
[ -z "$d" ] && continue
|
||||||
|
all_domains_string="$all_domains_string$d"$'\n'
|
||||||
|
done <<< "$u_domains"
|
||||||
|
done <<< "$users"
|
||||||
|
|
||||||
while IFS= read -r username; do
|
while IFS= read -r username; do
|
||||||
[ -z "$username" ] && continue
|
[ -z "$username" ] && continue
|
||||||
local user_domains
|
local user_domains
|
||||||
@@ -1798,27 +1889,24 @@ optimize_level_2_memory() {
|
|||||||
current_max="?"
|
current_max="?"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Get recommendations - use profile if available, otherwise use traffic-based
|
# Get recommendations - use profile if available, otherwise use intelligent three-constraint model
|
||||||
local recommended_max
|
local recommended_max
|
||||||
if [ "$profiles_exist" = "1" ] && [ -f "/tmp/php-domain-profiles/$domain.profile" ]; then
|
|
||||||
recommended_max=$(get_max_children_recommendation "$domain" "$username")
|
|
||||||
else
|
|
||||||
# Fallback to traffic-based (old method)
|
|
||||||
local traffic_rpm
|
|
||||||
traffic_rpm=$(get_domain_peak_concurrent "$domain" 2>/dev/null || echo "0")
|
|
||||||
[ "$traffic_rpm" = "?" ] && traffic_rpm="0"
|
|
||||||
recommended_max=$((traffic_rpm > 5 ? traffic_rpm + 10 : 5))
|
|
||||||
fi
|
|
||||||
|
|
||||||
local recommended_memory
|
local recommended_memory
|
||||||
if [ "$profiles_exist" = "1" ] && [ -f "/tmp/php-domain-profiles/$domain.profile" ]; then
|
if [ "$profiles_exist" = "1" ] && [ -f "/tmp/php-domain-profiles/$domain.profile" ]; then
|
||||||
|
recommended_max=$(get_max_children_recommendation "$domain" "$username")
|
||||||
recommended_memory=$(get_memory_limit_recommendation "$domain" "$username")
|
recommended_memory=$(get_memory_limit_recommendation "$domain" "$username")
|
||||||
else
|
else
|
||||||
# Fallback to traffic-based (old method)
|
# Use intelligent three-constraint model (same as Level 5)
|
||||||
local traffic_rpm
|
local traffic_pct
|
||||||
traffic_rpm=$(get_domain_peak_concurrent "$domain" 2>/dev/null || echo "0")
|
traffic_pct=$(get_domain_traffic_percentage "$username" "$domain" "$all_domains_string" 2>/dev/null | cut -d'|' -f1)
|
||||||
[ "$traffic_rpm" = "?" ] && traffic_rpm="0"
|
traffic_pct=${traffic_pct:-50}
|
||||||
recommended_memory=$(calculate_optimal_memory_limit "$username" "$domain" "$traffic_rpm")
|
|
||||||
|
# Call intelligent three-constraint function
|
||||||
|
local intel_result
|
||||||
|
intel_result=$(calculate_optimal_php_settings_intelligent "$username" "$total_ram_mb" "$server_capacity" "$traffic_pct" 2>/dev/null || echo "20|dynamic|1|5|ERROR|Failed")
|
||||||
|
|
||||||
|
recommended_max=$(echo "$intel_result" | cut -d'|' -f1)
|
||||||
|
recommended_memory=$(calculate_optimal_memory_limit "$username" "$domain" "$recommended_max" 2>/dev/null || echo "128M")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
recommended_max_children["$domain"]="$recommended_max"
|
recommended_max_children["$domain"]="$recommended_max"
|
||||||
@@ -1839,6 +1927,46 @@ optimize_level_2_memory() {
|
|||||||
done <<< "$user_domains"
|
done <<< "$user_domains"
|
||||||
done <<< "$users"
|
done <<< "$users"
|
||||||
|
|
||||||
|
# CRITICAL VALIDATION: Check if combined recommendations exceed safe limits
|
||||||
|
cecho "${CYAN}Step 2b: Validating capacity...${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
local total_recommended_max_children=0
|
||||||
|
local avg_memory_per_process=$server_memory_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))
|
||||||
|
|
||||||
|
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}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Scale down all recommendations proportionally
|
||||||
|
local scale_factor
|
||||||
|
scale_factor=$((max_safe_php_fpm * 100 / total_recommended_memory))
|
||||||
|
|
||||||
|
for domain in "${!recommended_max_children[@]}"; do
|
||||||
|
local rec_max="${recommended_max_children[$domain]}"
|
||||||
|
[ -z "$rec_max" ] && continue
|
||||||
|
rec_max=$((rec_max * scale_factor / 100))
|
||||||
|
[ "$rec_max" -lt 5 ] && rec_max=5
|
||||||
|
recommended_max_children["$domain"]="$rec_max"
|
||||||
|
done
|
||||||
|
cecho "${CYAN}Applied proportional scaling (${scale_factor}%)${NC}"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
if [ "$changes_needed" -eq 0 ]; then
|
if [ "$changes_needed" -eq 0 ]; then
|
||||||
cecho "${GREEN}${BOLD}✓ All domains already optimized${NC}"
|
cecho "${GREEN}${BOLD}✓ All domains already optimized${NC}"
|
||||||
@@ -2006,6 +2134,17 @@ optimize_level_3_advanced() {
|
|||||||
cecho " Status: ${WHITE}${status}${NC}"
|
cecho " Status: ${WHITE}${status}${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
|
# Calculate server capacity for intelligent three-constraint model
|
||||||
|
local server_capacity_result
|
||||||
|
server_capacity_result=$(calculate_server_capacity "$total_ram_mb")
|
||||||
|
local server_capacity
|
||||||
|
server_capacity=$(echo "$server_capacity_result" | cut -d'|' -f1)
|
||||||
|
local server_memory_per_process
|
||||||
|
server_memory_per_process=$(echo "$server_capacity_result" | cut -d'|' -f3)
|
||||||
|
cecho " Server PHP-FPM capacity: ${WHITE}${server_capacity}${NC} max_children"
|
||||||
|
cecho " Using intelligent three-constraint model: Memory + Traffic + Fair Share"
|
||||||
|
echo ""
|
||||||
|
|
||||||
# Check if profiles exist
|
# Check if profiles exist
|
||||||
local profiles_exist=0
|
local profiles_exist=0
|
||||||
if [ -d "/tmp/php-domain-profiles" ] && [ "$(ls -1 /tmp/php-domain-profiles/*.profile 2>/dev/null | wc -l)" -gt 0 ]; then
|
if [ -d "/tmp/php-domain-profiles" ] && [ "$(ls -1 /tmp/php-domain-profiles/*.profile 2>/dev/null | wc -l)" -gt 0 ]; then
|
||||||
@@ -2029,6 +2168,18 @@ optimize_level_3_advanced() {
|
|||||||
local users
|
local users
|
||||||
users=$(list_all_users)
|
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=""
|
||||||
|
while IFS= read -r u; do
|
||||||
|
[ -z "$u" ] && continue
|
||||||
|
u_domains=$(get_user_domains "$u")
|
||||||
|
while IFS= read -r d; do
|
||||||
|
[ -z "$d" ] && continue
|
||||||
|
all_domains_string="$all_domains_string$d"$'\n'
|
||||||
|
done <<< "$u_domains"
|
||||||
|
done <<< "$users"
|
||||||
|
|
||||||
while IFS= read -r username; do
|
while IFS= read -r username; do
|
||||||
[ -z "$username" ] && continue
|
[ -z "$username" ] && continue
|
||||||
local user_domains
|
local user_domains
|
||||||
@@ -2048,14 +2199,18 @@ optimize_level_3_advanced() {
|
|||||||
recommended_memory_limit["$domain"]=$(get_memory_limit_recommendation "$domain" "$username")
|
recommended_memory_limit["$domain"]=$(get_memory_limit_recommendation "$domain" "$username")
|
||||||
recommended_max_requests["$domain"]=$(get_max_requests_recommendation "$domain")
|
recommended_max_requests["$domain"]=$(get_max_requests_recommendation "$domain")
|
||||||
else
|
else
|
||||||
# Fallback to traffic-based (old method)
|
# Use intelligent three-constraint model (same as Level 5)
|
||||||
local traffic_rpm
|
local traffic_pct
|
||||||
traffic_rpm=$(get_domain_peak_concurrent "$domain" 2>/dev/null || echo "0")
|
traffic_pct=$(get_domain_traffic_percentage "$username" "$domain" "$all_domains_string" 2>/dev/null | cut -d'|' -f1)
|
||||||
[ "$traffic_rpm" = "?" ] && traffic_rpm="0"
|
traffic_pct=${traffic_pct:-50}
|
||||||
|
|
||||||
recommended_max_children["$domain"]=$((traffic_rpm > 5 ? traffic_rpm + 10 : 5))
|
# Call intelligent three-constraint function
|
||||||
recommended_memory_limit["$domain"]=$(calculate_optimal_memory_limit "$username" "$domain" "$traffic_rpm")
|
local intel_result
|
||||||
recommended_max_requests["$domain"]=$(calculate_optimal_max_requests "$traffic_rpm")
|
intel_result=$(calculate_optimal_php_settings_intelligent "$username" "$total_ram_mb" "$server_capacity" "$traffic_pct" 2>/dev/null || echo "20|dynamic|1|5|ERROR|Failed")
|
||||||
|
|
||||||
|
recommended_max_children["$domain"]=$(echo "$intel_result" | cut -d'|' -f1)
|
||||||
|
recommended_memory_limit["$domain"]=$(calculate_optimal_memory_limit "$username" "$domain" "$recommended_max_children[$domain]" 2>/dev/null || echo "128M")
|
||||||
|
recommended_max_requests["$domain"]=$(calculate_optimal_max_requests "$recommended_max_children[$domain]" 2>/dev/null || echo "0")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local current_max
|
local current_max
|
||||||
@@ -2088,6 +2243,46 @@ optimize_level_3_advanced() {
|
|||||||
done <<< "$user_domains"
|
done <<< "$user_domains"
|
||||||
done <<< "$users"
|
done <<< "$users"
|
||||||
|
|
||||||
|
# CRITICAL VALIDATION: Check if combined recommendations exceed safe limits
|
||||||
|
cecho "${CYAN}Step 2b: Validating capacity...${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
local total_recommended_max_children=0
|
||||||
|
local avg_memory_per_process=$server_memory_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))
|
||||||
|
|
||||||
|
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}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Scale down all recommendations proportionally
|
||||||
|
local scale_factor
|
||||||
|
scale_factor=$((max_safe_php_fpm * 100 / total_recommended_memory))
|
||||||
|
|
||||||
|
for domain in "${!recommended_max_children[@]}"; do
|
||||||
|
local rec_max="${recommended_max_children[$domain]}"
|
||||||
|
[ -z "$rec_max" ] && continue
|
||||||
|
rec_max=$((rec_max * scale_factor / 100))
|
||||||
|
[ "$rec_max" -lt 5 ] && rec_max=5
|
||||||
|
recommended_max_children["$domain"]="$rec_max"
|
||||||
|
done
|
||||||
|
cecho "${CYAN}Applied proportional scaling (${scale_factor}%)${NC}"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
if [ "$changes_needed" -eq 0 ]; then
|
if [ "$changes_needed" -eq 0 ]; then
|
||||||
cecho "${GREEN}${BOLD}✓ All domains already optimized${NC}"
|
cecho "${GREEN}${BOLD}✓ All domains already optimized${NC}"
|
||||||
|
|||||||
Reference in New Issue
Block a user