Files
cschantz dea6f27b4d Fix ESCAPE issues in multiple library files
- lib/domain-discovery.sh: Added -- to grep command (1 fix)
- lib/reference-db.sh: Added -- to grep command (1 fix)
- lib/user-manager.sh: Added -- to grep command (1 fix)
- lib/email-functions.sh: Added -- to awk and grep commands (2 fixes)
- lib/php-config-manager.sh: Added -- to grep commands (3 fixes)
- lib/php-detector.sh: Added -- to grep command (1 fix)
Total: 9 ESCAPE fixes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-09 16:38:55 -05:00

447 lines
16 KiB
Bash

#!/bin/bash
################################################################################
# PHP Detector Library
# Part of Server Toolkit - PHP & Server Optimizer
#
# Purpose: Detect all PHP configurations, pools, versions, and settings
# Author: Server Toolkit Team
# Dependencies: system-detect.sh, user-manager.sh
################################################################################
# Source dependencies (if not already loaded)
if [ -z "$SYS_CONTROL_PANEL" ]; then
_LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "$_LIB_DIR/lib/system-detect.sh" 2>/dev/null
source "$_LIB_DIR/lib/user-manager.sh" 2>/dev/null
fi
################################################################################
# PHP Version Detection
################################################################################
# Detect all installed PHP versions on the system
detect_installed_php_versions() {
local -a php_versions=()
# cPanel EA-PHP
if [ -d "/opt/cpanel" ]; then
while IFS= read -r dir; do
local version=$(basename "$dir" | sed 's/ea-php//')
php_versions+=("ea-php$version")
done < <(find /opt/cpanel -maxdepth 1 -type d -name "ea-php*" 2>/dev/null | sort)
fi
# CloudLinux Alt-PHP
if [ -d "/opt/alt" ]; then
while IFS= read -r dir; do
local version=$(basename "$dir" | sed 's/php//')
php_versions+=("alt-php$version")
done < <(find /opt/alt -maxdepth 1 -type d -name "php*" 2>/dev/null | grep -E "php[0-9]" | sort)
fi
# Plesk PHP
if [ -d "/opt/plesk/php" ]; then
while IFS= read -r dir; do
local version=$(basename "$dir")
php_versions+=("plesk-php$version")
done < <(find /opt/plesk/php -maxdepth 1 -type d -name "[0-9]*" 2>/dev/null | sort)
fi
# System PHP
if command -v php &>/dev/null; then
local sys_version=$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;' 2>/dev/null)
[ -n "$sys_version" ] && php_versions+=("system-php$sys_version")
fi
# Return array
printf '%s\n' "${php_versions[@]}"
}
# Get PHP version for a specific domain/user
detect_php_version_for_domain() {
local username="$1"
local domain="$2"
case "$SYS_CONTROL_PANEL" in
cpanel)
# Check userdata for PHP version
local userdata_file="${SYS_CPANEL_USERDATA_DIR:-/var/cpanel/userdata}/$username/$domain"
if [ -f "$userdata_file" ]; then
local php_ver=$(grep "phpversion:" -- "$userdata_file" | awk '{print $2}' | tr -d "'\"")
echo "$php_ver"
return 0
fi
# Fallback: Check FPM pool config
local pool_config=$(find /opt/cpanel/ea-php*/root/etc/php-fpm.d/ -name "$username.conf" 2>/dev/null | head -1)
if [ -n "$pool_config" ]; then
local php_path=$(dirname "$(dirname "$(dirname "$pool_config")")")
basename "$php_path"
return 0
fi
;;
plesk)
# Query Plesk database
if command -v plesk &>/dev/null; then
plesk bin site -i "$domain" 2>/dev/null | grep "PHP version" | awk '{print $NF}'
return 0
fi
;;
interworx)
# Check SiteWorx config
local domain_conf="/home/$username/var/$domain/siteworx.conf"
if [ -f "$domain_conf" ]; then
grep "php_version" "$domain_conf" | cut -d'=' -f2
return 0
fi
;;
esac
# Fallback: Try to execute PHP as user
su -s /bin/bash "$username" -c "php -r 'echo PHP_MAJOR_VERSION.\".\".PHP_MINOR_VERSION;'" 2>/dev/null
}
################################################################################
# PHP Configuration File Detection
################################################################################
# Find ALL php.ini files affecting a domain (in priority order)
find_all_php_configs() {
local username="$1"
local domain="$2"
local php_version="${3:-}" # Optional: e.g., "82" or "8.2" or "ea-php82"
declare -a config_files=()
# Normalize PHP version format
local php_ver_short=$(echo "$php_version" | grep -oE '[0-9]+' | head -c2)
local php_ver_dot="${php_ver_short:0:1}.${php_ver_short:1}"
# PRIORITY 1: Per-Directory .user.ini files
if [ -d "/home/$username" ]; then
while IFS= read -r file; do
config_files+=("P1|$file|.user.ini")
done < <(find "/home/$username" -name ".user.ini" -type f 2>/dev/null)
fi
# Check Plesk domain root
if [ -d "/var/www/vhosts/$domain" ]; then
while IFS= read -r file; do
config_files+=("P1|$file|.user.ini")
done < <(find "/var/www/vhosts/$domain" -name ".user.ini" -type f 2>/dev/null)
fi
# PRIORITY 2: User-Specific php.ini files
local user_configs=(
"/home/$username/public_html/php.ini"
"/home/$username/php.ini"
"/home/$username/.php/$php_ver_dot/php.ini"
"/home/$username/.php/$php_ver_short/php.ini"
"/home/$username/etc/php.ini"
"/home/$username/etc/php$php_ver_short/php.ini"
"/home/$username/var/$domain/etc/php.ini" # InterWorx
"/var/www/vhosts/system/$domain/etc/php.ini" # Plesk
)
for config in "${user_configs[@]}"; do
[ -f "$config" ] && config_files+=("P2|$config|user php.ini")
done
# PRIORITY 3: Pool/Version-Specific php.ini
if [ -n "$php_ver_short" ]; then
# cPanel EA-PHP
local cpanel_ini="/opt/cpanel/ea-php${php_ver_short}/root/etc/php.ini"
[ -f "$cpanel_ini" ] && config_files+=("P3|$cpanel_ini|pool php.ini")
# cPanel EA-PHP additional .ini files
if [ -d "/opt/cpanel/ea-php${php_ver_short}/root/etc/php.d" ]; then
while IFS= read -r file; do
config_files+=("P3|$file|pool php.d")
done < <(find "/opt/cpanel/ea-php${php_ver_short}/root/etc/php.d" -name "*.ini" -type f 2>/dev/null | sort)
fi
# CloudLinux Alt-PHP
local alt_ini="/opt/alt/php${php_ver_short}/etc/php.ini"
[ -f "$alt_ini" ] && config_files+=("P3|$alt_ini|alt-php ini")
# Plesk PHP
local plesk_ini="/opt/plesk/php/$php_ver_dot/etc/php.ini"
[ -f "$plesk_ini" ] && config_files+=("P3|$plesk_ini|plesk php.ini")
fi
# PRIORITY 4: System-Wide
[ -f "/etc/php.ini" ] && config_files+=("P4|/etc/php.ini|system php.ini")
# Return the array (priority|path|description)
printf '%s\n' "${config_files[@]}"
}
# Get effective value of a PHP setting for a specific user
get_effective_php_setting() {
local username="$1"
local setting="$2"
# Query PHP directly as the user (most accurate!)
su -s /bin/bash "$username" -c "php -r 'echo ini_get(\"$setting\");'" 2>/dev/null
}
# Get all effective PHP settings for a user
get_all_php_settings() {
local username="$1"
# Get all settings in parseable format
su -s /bin/bash "$username" -c "php -r 'foreach(ini_get_all() as \$k=>\$v) { echo \$k.\"=\".\$v[\"local_value\"].\"\\n\"; }'" 2>/dev/null
}
################################################################################
# PHP-FPM Pool Detection
################################################################################
# Find PHP-FPM pool configuration for a user/domain
find_fpm_pool_config() {
local username="$1"
local domain="$2"
local php_version="${3:-}"
local pool_config=""
# cPanel EA-PHP pools - search username FIRST (this is how cPanel works!)
if [ -n "$php_version" ]; then
# Try username-based config (most common)
pool_config="/opt/cpanel/$php_version/root/etc/php-fpm.d/$username.conf"
[ -f "$pool_config" ] && echo "$pool_config" && return 0
# Try domain-based config (rare, but possible)
if [ -n "$domain" ]; then
pool_config="/opt/cpanel/$php_version/root/etc/php-fpm.d/$domain.conf"
[ -f "$pool_config" ] && echo "$pool_config" && return 0
fi
fi
# Search all EA-PHP versions - try username FIRST, then domain
pool_config=$(find /opt/cpanel/ea-php*/root/etc/php-fpm.d/ -name "$username.conf" 2>/dev/null | head -1)
[ -n "$pool_config" ] && echo "$pool_config" && return 0
if [ -n "$domain" ]; then
pool_config=$(find /opt/cpanel/ea-php*/root/etc/php-fpm.d/ -name "$domain.conf" 2>/dev/null | head -1)
[ -n "$pool_config" ] && echo "$pool_config" && return 0
fi
# Plesk pools
if [ -n "$domain" ]; then
pool_config="/etc/php-fpm.d/plesk-php*-fpm/$domain.conf"
[ -f "$pool_config" ] && echo "$pool_config" && return 0
fi
# InterWorx pools
if [ -n "$domain" ]; then
pool_config="/home/$username/var/$domain/php-fpm.conf"
[ -f "$pool_config" ] && echo "$pool_config" && return 0
fi
return 1
}
# Parse PHP-FPM pool config and extract all settings
parse_fpm_pool_config() {
local pool_config="$1"
[ ! -f "$pool_config" ] && return 1
# Extract key settings
local pm=$(grep "^pm\s*=" "$pool_config" | awk -F'=' '{print $2}' | tr -d ' ')
local max_children=$(grep "^pm.max_children" "$pool_config" | awk -F'=' '{print $2}' | tr -d ' ')
local start_servers=$(grep "^pm.start_servers" "$pool_config" | awk -F'=' '{print $2}' | tr -d ' ')
local min_spare=$(grep "^pm.min_spare_servers" "$pool_config" | awk -F'=' '{print $2}' | tr -d ' ')
local max_spare=$(grep "^pm.max_spare_servers" "$pool_config" | awk -F'=' '{print $2}' | tr -d ' ')
local max_requests=$(grep "^pm.max_requests" "$pool_config" | awk -F'=' '{print $2}' | tr -d ' ')
local idle_timeout=$(grep "^pm.process_idle_timeout" "$pool_config" | awk -F'=' '{print $2}' | tr -d ' ')
local request_terminate=$(grep "^request_terminate_timeout" "$pool_config" | awk -F'=' '{print $2}' | tr -d ' ')
local slowlog_timeout=$(grep "^request_slowlog_timeout" "$pool_config" | awk -F'=' '{print $2}' | tr -d ' ')
# Output in key=value format
echo "pm=$pm"
echo "pm.max_children=$max_children"
echo "pm.start_servers=$start_servers"
echo "pm.min_spare_servers=$min_spare"
echo "pm.max_spare_servers=$max_spare"
echo "pm.max_requests=$max_requests"
echo "pm.process_idle_timeout=$idle_timeout"
echo "request_terminate_timeout=$request_terminate"
echo "request_slowlog_timeout=$slowlog_timeout"
}
# Get current FPM process count for a pool
get_fpm_process_count() {
[ -z "$1" ] && return 1
local pool_name="$1" # Usually username or domain
ps aux | grep -E "php-fpm.*pool\s+${pool_name}" | grep -v grep | wc -l
}
# Get memory usage per FPM process for a pool
get_fpm_memory_usage() {
[ -z "$1" ] && return 1
local pool_name="$1"
# Get average memory per process (in KB)
ps aux | grep -E "php-fpm.*pool\s+${pool_name}" | grep -v grep | awk '{sum+=$6; count++} END {if(count>0) print int(sum/count); else print 0}'
}
################################################################################
# PHP Log File Detection
################################################################################
# Find PHP error logs for a user/domain
find_php_error_logs() {
local username="$1"
local domain="$2"
declare -a log_files=()
# Common error log locations
local possible_logs=(
"/home/$username/logs/error_log"
"/home/$username/public_html/error_log"
"/home/$username/logs/$domain.error_log"
"/var/www/vhosts/$domain/logs/error_log"
"/home/$username/var/$domain/logs/error_log"
)
for log in "${possible_logs[@]}"; do
[ -f "$log" ] && log_files+=("$log")
done
printf '%s\n' "${log_files[@]}"
}
# Find PHP-FPM error logs
find_fpm_error_logs() {
local username="$1"
local php_version="${2:-}"
declare -a log_files=()
if [ -n "$php_version" ]; then
# Specific version
log_files+=("/opt/cpanel/$php_version/root/usr/var/log/php-fpm/$username-error.log")
else
# All versions
while IFS= read -r log; do
log_files+=("$log")
done < <(find /opt/cpanel/ea-php*/root/usr/var/log/php-fpm/ -name "$username-error.log" 2>/dev/null)
fi
printf '%s\n' "${log_files[@]}"
}
# Find PHP-FPM slow logs
find_fpm_slow_logs() {
local username="$1"
local php_version="${2:-}"
declare -a log_files=()
if [ -n "$php_version" ]; then
log_files+=("/opt/cpanel/$php_version/root/usr/var/log/php-fpm/$username-slow.log")
else
while IFS= read -r log; do
log_files+=("$log")
done < <(find /opt/cpanel/ea-php*/root/usr/var/log/php-fpm/ -name "$username-slow.log" 2>/dev/null)
fi
printf '%s\n' "${log_files[@]}"
}
################################################################################
# OPcache Detection
################################################################################
# Check if OPcache is enabled for a user
check_opcache_enabled() {
local username="$1"
su -s /bin/bash "$username" -c "php -r 'echo (function_exists(\"opcache_get_status\") && opcache_get_status() !== false) ? \"1\" : \"0\";'" 2>/dev/null
}
# Get OPcache statistics for a user
get_opcache_stats() {
local username="$1"
su -s /bin/bash "$username" -c "php -r 'if(function_exists(\"opcache_get_status\")) { \$s=opcache_get_status(); echo \"enabled=\".(\$s!==false?1:0).\"\\n\"; if(\$s) { echo \"memory_used=\".\$s[\"memory_usage\"][\"used_memory\"].\"\\n\"; echo \"memory_free=\".\$s[\"memory_usage\"][\"free_memory\"].\"\\n\"; echo \"memory_wasted=\".\$s[\"memory_usage\"][\"wasted_memory\"].\"\\n\"; echo \"num_cached_scripts=\".\$s[\"opcache_statistics\"][\"num_cached_scripts\"].\"\\n\"; echo \"max_cached_scripts=\".\$s[\"opcache_statistics\"][\"max_cached_scripts\"].\"\\n\"; echo \"hits=\".\$s[\"opcache_statistics\"][\"hits\"].\"\\n\"; echo \"misses=\".\$s[\"opcache_statistics\"][\"misses\"].\"\\n\"; } }'" 2>/dev/null
}
# Calculate OPcache hit rate
calculate_opcache_hit_rate() {
local username="$1"
local stats=$(get_opcache_stats "$username")
[ -z "$stats" ] && echo "0" && return 1
local hits=$(echo "$stats" | grep "^hits=" | cut -d'=' -f2)
local misses=$(echo "$stats" | grep "^misses=" | cut -d'=' -f2)
[ -z "$hits" ] || [ -z "$misses" ] && echo "0" && return 1
[ "$hits" -eq 0 ] && [ "$misses" -eq 0 ] && echo "0" && return 1
local total=$((hits + misses))
local hit_rate=$((hits * 100 / total))
echo "$hit_rate"
}
################################################################################
# Helper Functions
################################################################################
# Check if PHP-FPM is in use (vs mod_php)
is_using_php_fpm() {
# Check if any PHP-FPM processes are running
pgrep php-fpm &>/dev/null && return 0
return 1
}
# Get PHP binary path for a specific version
get_php_binary_path() {
local php_version="$1"
case "$php_version" in
ea-php*)
echo "/opt/cpanel/$php_version/root/usr/bin/php"
;;
alt-php*)
local ver=$(echo "$php_version" | sed 's/alt-php//')
echo "/opt/alt/php$ver/usr/bin/php"
;;
plesk-php*)
local ver=$(echo "$php_version" | sed 's/plesk-php//')
echo "/opt/plesk/php/$ver/bin/php"
;;
*)
which php
;;
esac
}
# Export all functions
export -f detect_installed_php_versions
export -f detect_php_version_for_domain
export -f find_all_php_configs
export -f get_effective_php_setting
export -f get_all_php_settings
export -f find_fpm_pool_config
export -f parse_fpm_pool_config
export -f get_fpm_process_count
export -f get_fpm_memory_usage
export -f find_php_error_logs
export -f find_fpm_error_logs
export -f find_fpm_slow_logs
export -f check_opcache_enabled
export -f get_opcache_stats
export -f calculate_opcache_hit_rate
export -f is_using_php_fpm
export -f get_php_binary_path