#!/bin/bash ############################################################################# # System Detection Library # Runtime detection of control panels, OS, paths, and system resources # No persistent caching - detects fresh every time ############################################################################# # Source common functions if not already loaded if [ -z "$TOOLKIT_BASE_DIR" ]; then SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/common-functions.sh" fi # Global variables (session-only) - only initialize if not already set if [ -z "$SYS_DETECTION_COMPLETE" ]; then export SYS_CONTROL_PANEL="" export SYS_CONTROL_PANEL_VERSION="" export SYS_OS_TYPE="" export SYS_OS_VERSION="" export SYS_WEB_SERVER="" export SYS_WEB_SERVER_VERSION="" export SYS_DB_TYPE="" export SYS_DB_VERSION="" export SYS_LOG_DIR="" fi export SYS_USER_HOME_BASE="" export SYS_PHP_VERSIONS=() export SYS_CLOUDFLARE_ACTIVE="" export SYS_FIREWALL="" export SYS_FIREWALL_VERSION="" export SYS_FIREWALL_ACTIVE="" ############################################################################# # CONTROL PANEL DETECTION ############################################################################# detect_control_panel() { # Silent detection if already detected [ -n "$SYS_DETECTION_COMPLETE" ] || print_info "Detecting control panel..." # cPanel if [ -f "/usr/local/cpanel/version" ]; then SYS_CONTROL_PANEL="cpanel" SYS_CONTROL_PANEL_VERSION=$(cat /usr/local/cpanel/version) SYS_LOG_DIR="/var/log/apache2/domlogs" SYS_USER_HOME_BASE="/home" # Alternative log locations for cPanel [ ! -d "$SYS_LOG_DIR" ] && SYS_LOG_DIR="/usr/local/apache/domlogs" print_success "Detected cPanel v${SYS_CONTROL_PANEL_VERSION}" return 0 fi # Plesk if [ -f "/usr/local/psa/version" ]; then SYS_CONTROL_PANEL="plesk" SYS_CONTROL_PANEL_VERSION=$(cat /usr/local/psa/version | head -1) # Plesk uses /var/www/vhosts as base SYS_USER_HOME_BASE="/var/www/vhosts" # Log directory depends on Plesk version # Plesk 18.0.50+ uses /var/www/vhosts/DOMAIN/logs # Plesk <18.0.50 uses /var/www/vhosts/system/DOMAIN/logs # Set marker path - tools will use plesk_get_logdir() for actual path SYS_LOG_DIR="/var/www/vhosts/system" # Source Plesk helpers for advanced functionality if [ -f "$LIB_DIR/plesk-helpers.sh" ]; then source "$LIB_DIR/plesk-helpers.sh" fi print_success "Detected Plesk v${SYS_CONTROL_PANEL_VERSION}" return 0 fi # InterWorx if [ -d "/usr/local/interworx" ] || [ -f "/etc/interworx/iworx.ini" ]; then SYS_CONTROL_PANEL="interworx" if [ -f "/usr/local/interworx/iworx/version.php" ]; then SYS_CONTROL_PANEL_VERSION=$(grep -oP "VERSION = '\K[^']+" /usr/local/interworx/iworx/version.php 2>/dev/null || echo "Unknown") fi # InterWorx stores logs in /home/user/var/domain.com/logs/ # We set a marker path that tools will recognize needs special handling SYS_LOG_DIR="/home/*/var/*/logs" # InterWorx uses /chroot/home (with /home as symlink) # Use actual path as system doesn't show /home properly SYS_USER_HOME_BASE="/chroot/home" print_success "Detected InterWorx v${SYS_CONTROL_PANEL_VERSION}" return 0 fi # No control panel detected SYS_CONTROL_PANEL="none" SYS_LOG_DIR="/var/log/httpd" [ ! -d "$SYS_LOG_DIR" ] && SYS_LOG_DIR="/var/log/apache2" SYS_USER_HOME_BASE="/home" print_warning "No control panel detected (standalone server)" return 1 } ############################################################################# # OPERATING SYSTEM DETECTION ############################################################################# detect_os() { [ -n "$SYS_DETECTION_COMPLETE" ] || print_info "Detecting operating system..." if [ -f /etc/os-release ]; then source /etc/os-release SYS_OS_TYPE="$ID" SYS_OS_VERSION="$VERSION_ID" # Normalize OS names case "$SYS_OS_TYPE" in rhel|centos|almalinux|rocky|cloudlinux) SYS_OS_TYPE=$(echo "$NAME" | awk '{print tolower($1)}') ;; esac print_success "Detected $NAME $VERSION_ID" elif [ -f /etc/redhat-release ]; then local release_info=$(cat /etc/redhat-release) SYS_OS_TYPE="centos" SYS_OS_VERSION=$(echo "$release_info" | grep -oP '\d+\.\d+' | head -1) print_success "Detected $release_info" else SYS_OS_TYPE="unknown" SYS_OS_VERSION="unknown" print_warning "Could not detect OS" fi # Check for CloudLinux if [ -f /etc/sysconfig/cloudlinux ] || [ -f /usr/bin/cloudlinux-config ]; then print_info "CloudLinux detected" export SYS_CLOUDLINUX="yes" fi } ############################################################################# # WEB SERVER DETECTION ############################################################################# detect_web_server() { [ -n "$SYS_DETECTION_COMPLETE" ] || print_info "Detecting web server..." # Apache if command_exists httpd; then SYS_WEB_SERVER="apache" SYS_WEB_SERVER_VERSION=$(httpd -v 2>/dev/null | grep -oP 'Apache/\K[\d.]+' | head -1) print_success "Detected Apache ${SYS_WEB_SERVER_VERSION}" return 0 elif command_exists apache2; then SYS_WEB_SERVER="apache" SYS_WEB_SERVER_VERSION=$(apache2 -v 2>/dev/null | grep -oP 'Apache/\K[\d.]+' | head -1) print_success "Detected Apache ${SYS_WEB_SERVER_VERSION}" return 0 fi # Nginx if command_exists nginx; then SYS_WEB_SERVER="nginx" SYS_WEB_SERVER_VERSION=$(nginx -v 2>&1 | grep -oP 'nginx/\K[\d.]+' 2>/dev/null) print_success "Detected Nginx ${SYS_WEB_SERVER_VERSION}" return 0 fi # LiteSpeed if [ -f /usr/local/lsws/bin/lswsctrl ]; then SYS_WEB_SERVER="litespeed" SYS_WEB_SERVER_VERSION=$(/usr/local/lsws/bin/lswsctrl version 2>/dev/null | grep -oP 'LiteSpeed/\K[\d.]+' | head -1) print_success "Detected LiteSpeed ${SYS_WEB_SERVER_VERSION}" return 0 fi # OpenLiteSpeed if command_exists /usr/local/lsws/bin/openlitespeed; then SYS_WEB_SERVER="openlitespeed" SYS_WEB_SERVER_VERSION=$(cat /usr/local/lsws/VERSION 2>/dev/null) print_success "Detected OpenLiteSpeed ${SYS_WEB_SERVER_VERSION}" return 0 fi SYS_WEB_SERVER="unknown" print_warning "Could not detect web server" return 1 } ############################################################################# # DATABASE DETECTION ############################################################################# detect_database() { [ -n "$SYS_DETECTION_COMPLETE" ] || print_info "Detecting database server..." if command_exists mysql; then local version_output=$(mysql --version 2>/dev/null) if echo "$version_output" | grep -qi "mariadb"; then SYS_DB_TYPE="mariadb" SYS_DB_VERSION=$(echo "$version_output" | grep -oP '\d+\.\d+\.\d+' | head -1) print_success "Detected MariaDB ${SYS_DB_VERSION}" else SYS_DB_TYPE="mysql" SYS_DB_VERSION=$(echo "$version_output" | grep -oP '\d+\.\d+\.\d+' | head -1) print_success "Detected MySQL ${SYS_DB_VERSION}" fi return 0 fi SYS_DB_TYPE="none" print_warning "No MySQL/MariaDB detected" return 1 } ############################################################################# # PHP VERSION DETECTION ############################################################################# detect_php_versions() { [ -n "$SYS_DETECTION_COMPLETE" ] || print_info "Detecting PHP versions..." SYS_PHP_VERSIONS=() # Check default PHP if command_exists php; then local default_version=$(php -v 2>/dev/null | grep -oP '^PHP \K[\d.]+' | head -1) [ -n "$default_version" ] && SYS_PHP_VERSIONS+=("$default_version") fi # Check EA-PHP versions (cPanel) - fast path parsing if [ "$SYS_CONTROL_PANEL" = "cpanel" ]; then for php_path in /opt/cpanel/ea-php*/root/usr/bin/php; do if [ -x "$php_path" ]; then # Extract version from path (ea-php82 -> 8.2) local ver=$(echo "$php_path" | grep -oP 'ea-php\K\d+') if [ -n "$ver" ]; then # Convert 82 -> 8.2, 81 -> 8.1, etc local major="${ver:0:1}" local minor="${ver:1}" # Get patch version from php -v only if needed (slower but accurate) local full_version=$($php_path -v 2>/dev/null | grep -oP '^PHP \K[\d.]+' | head -1) [ -n "$full_version" ] && SYS_PHP_VERSIONS+=("$full_version") fi fi done fi # Check Plesk PHP versions (/opt/plesk/php/) if [ "$SYS_CONTROL_PANEL" = "plesk" ]; then for php_path in /opt/plesk/php/*/bin/php; do if [ -x "$php_path" ]; then local full_version=$($php_path -v 2>/dev/null | grep -oP '^PHP \K[\d.]+' | head -1) [ -n "$full_version" ] && SYS_PHP_VERSIONS+=("$full_version") fi done fi # Check alt-php versions (CloudLinux) - fast path parsing for php_path in /opt/alt/php*/usr/bin/php; do if [ -x "$php_path" ]; then # Extract version from path (php74 -> 7.4) local ver=$(echo "$php_path" | grep -oP 'php\K\d+') if [ -n "$ver" ]; then local full_version=$($php_path -v 2>/dev/null | grep -oP '^PHP \K[\d.]+' | head -1) [ -n "$full_version" ] && SYS_PHP_VERSIONS+=("$full_version") fi fi done # Remove duplicates and sort by version SYS_PHP_VERSIONS=($(echo "${SYS_PHP_VERSIONS[@]}" | tr ' ' '\n' | sort -u -V)) if [ ${#SYS_PHP_VERSIONS[@]} -gt 0 ]; then print_success "Detected PHP versions: ${SYS_PHP_VERSIONS[*]}" else print_warning "No PHP installations detected" fi } ############################################################################# # CLOUDFLARE DETECTION ############################################################################# detect_cloudflare() { SYS_CLOUDFLARE_ACTIVE="no" # Check for mod_cloudflare if [ "$SYS_WEB_SERVER" = "apache" ]; then if httpd -M 2>/dev/null | grep -q cloudflare; then SYS_CLOUDFLARE_ACTIVE="yes" print_info "Cloudflare module detected" fi fi # Check for railgun - fast process check if pgrep -x railgun > /dev/null 2>&1; then SYS_CLOUDFLARE_ACTIVE="yes" print_info "Cloudflare Railgun detected" fi } ############################################################################# # FIREWALL DETECTION ############################################################################# detect_firewall() { [ -n "$SYS_DETECTION_COMPLETE" ] || print_info "Detecting firewall..." # CSF/LFD if [ -f "/etc/csf/csf.conf" ]; then SYS_FIREWALL="csf" # Fast version check - read from version.txt or parse csf script SYS_FIREWALL_VERSION=$(head -1 /etc/csf/version.txt 2>/dev/null || grep -oP 'my \$version = "\K[^"]+' /usr/sbin/csf 2>/dev/null | head -1 || echo "unknown") # Fast check: just check if lfd process is running if pgrep -x lfd > /dev/null 2>&1; then SYS_FIREWALL_ACTIVE="yes" print_success "Detected CSF ${SYS_FIREWALL_VERSION} (active)" else SYS_FIREWALL_ACTIVE="no" print_warning "Detected CSF ${SYS_FIREWALL_VERSION} (inactive)" fi export SYS_CSF_ACTIVE="${SYS_FIREWALL_ACTIVE}" return 0 fi # firewalld if command_exists firewall-cmd; then SYS_FIREWALL="firewalld" SYS_FIREWALL_VERSION=$(firewall-cmd --version 2>/dev/null || echo "unknown") if systemctl is-active --quiet firewalld 2>/dev/null; then SYS_FIREWALL_ACTIVE="yes" print_success "Detected firewalld ${SYS_FIREWALL_VERSION} (active)" else SYS_FIREWALL_ACTIVE="no" print_warning "Detected firewalld ${SYS_FIREWALL_VERSION} (inactive)" fi return 0 fi # iptables if command_exists iptables; then SYS_FIREWALL="iptables" SYS_FIREWALL_VERSION=$(iptables --version 2>/dev/null | grep -oP 'v\K[\d.]+' | head -1 || echo "unknown") # Fast check: just check filter table INPUT chain only (much faster than full -L) if [ "$(iptables -L INPUT -n 2>/dev/null | wc -l)" -gt 2 ]; then SYS_FIREWALL_ACTIVE="yes" print_success "Detected iptables ${SYS_FIREWALL_VERSION} (active)" else SYS_FIREWALL_ACTIVE="no" print_warning "Detected iptables ${SYS_FIREWALL_VERSION} (no rules)" fi return 0 fi # UFW if command_exists ufw; then SYS_FIREWALL="ufw" SYS_FIREWALL_VERSION=$(ufw version 2>/dev/null | grep -oP '\d+\.\d+\.\d+' | head -1 || echo "unknown") if ufw status 2>/dev/null | grep -q "Status: active"; then SYS_FIREWALL_ACTIVE="yes" print_success "Detected UFW ${SYS_FIREWALL_VERSION} (active)" else SYS_FIREWALL_ACTIVE="no" print_warning "Detected UFW ${SYS_FIREWALL_VERSION} (inactive)" fi return 0 fi SYS_FIREWALL="none" SYS_FIREWALL_ACTIVE="no" print_warning "No firewall detected" return 1 } ############################################################################# # SYSTEM RESOURCES (Comprehensive - like user's example) ############################################################################# get_system_resources() { local resources_file="${TEMP_SESSION_DIR}/system_resources.tmp" # CPU Information local cores=$(nproc) local load=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | sed 's/,//') local cpu_line=$(top -bn1 | grep "Cpu(s)") local cpu_idle=$(echo "$cpu_line" | awk '{print $8}' | sed 's/%id,//') local cpu_iowait=$(echo "$cpu_line" | awk '{print $10}' | sed 's/%wa,//') local cpu_used=$(awk "BEGIN {printf \"%.1f\", 100-$cpu_idle}") local load_percent=$(awk "BEGIN {printf \"%.0f\", ($load/$cores)*100}") # Memory Information - get all in one call local mem_info=$(free -h) local mem_total=$(echo "$mem_info" | awk '/^Mem:/ {print $2}') local mem_used=$(echo "$mem_info" | awk '/^Mem:/ {print $3}') local mem_available=$(echo "$mem_info" | awk '/^Mem:/ {print $7}') local mem_percent=$(free | awk '/^Mem:/ {printf "%.0f", $3/$2*100}') # Swap Information - from same free call local swap_total=$(echo "$mem_info" | awk '/^Swap:/ {print $2}') local swap_used=$(echo "$mem_info" | awk '/^Swap:/ {print $3}') local swap_percent=0 if [ "$swap_total" != "0B" ] && [ -n "$swap_total" ]; then swap_percent=$(free | awk '/^Swap:/ {if($2>0) printf "%.0f", $3/$2*100; else print "0"}') fi # Disk Information - single df call local disk_info=$(df -h / | awk 'NR==2 {print $2,$3,$5}') local disk_root_total=$(echo "$disk_info" | awk '{print $1}') local disk_root_used=$(echo "$disk_info" | awk '{print $2}') local disk_root_percent=$(echo "$disk_info" | awk '{print $3}') # Uptime local uptime_str=$(uptime -p) # Save to session file cat > "$resources_file" << EOF CPU_CORES=$cores CPU_USED=$cpu_used CPU_IOWAIT=$cpu_iowait LOAD_AVERAGE=$load LOAD_PERCENT=$load_percent MEM_TOTAL=$mem_total MEM_USED=$mem_used MEM_PERCENT=$mem_percent MEM_AVAILABLE=$mem_available SWAP_TOTAL=$swap_total SWAP_USED=$swap_used SWAP_PERCENT=$swap_percent DISK_ROOT_TOTAL=$disk_root_total DISK_ROOT_USED=$disk_root_used DISK_ROOT_PERCENT=$disk_root_percent UPTIME=$uptime_str EOF # Also export for immediate use export CPU_CORES=$cores export CPU_USED=$cpu_used export CPU_IOWAIT=$cpu_iowait export LOAD_AVERAGE=$load export LOAD_PERCENT=$load_percent export MEM_TOTAL=$mem_total export MEM_USED=$mem_used export MEM_PERCENT=$mem_percent } ############################################################################# # DISPLAY FUNCTIONS ############################################################################# show_system_info() { echo "" print_banner "System Information" # Control Panel echo -e "${BOLD}Control Panel:${NC}" if [ "$SYS_CONTROL_PANEL" != "none" ]; then echo " Type: $SYS_CONTROL_PANEL" echo " Version: $SYS_CONTROL_PANEL_VERSION" else echo " Type: Standalone (no control panel)" fi echo "" # Operating System echo -e "${BOLD}Operating System:${NC}" echo " OS: $SYS_OS_TYPE $SYS_OS_VERSION" echo " Kernel: $(uname -r)" [ "${SYS_CLOUDLINUX:-}" = "yes" ] && echo " CloudLinux: Enabled" echo "" # Web Server echo -e "${BOLD}Web Server:${NC}" echo " Type: $SYS_WEB_SERVER" echo " Version: $SYS_WEB_SERVER_VERSION" [ "$SYS_CLOUDFLARE_ACTIVE" = "yes" ] && echo " Cloudflare: Active" echo "" # Database echo -e "${BOLD}Database:${NC}" if [ "$SYS_DB_TYPE" != "none" ]; then echo " Type: $SYS_DB_TYPE" echo " Version: $SYS_DB_VERSION" else echo " Type: Not installed" fi echo "" # PHP echo -e "${BOLD}PHP Versions:${NC}" if [ ${#SYS_PHP_VERSIONS[@]} -gt 0 ]; then for version in "${SYS_PHP_VERSIONS[@]}"; do echo " - PHP $version" done else echo " None detected" fi echo "" # System Resources echo -e "${BOLD}System Resources:${NC}" echo " CPU Cores: $CPU_CORES" echo " CPU Usage: ${CPU_USED}% (actual)" echo " I/O Wait: ${CPU_IOWAIT}%" echo " Load Average: $LOAD_AVERAGE (${LOAD_PERCENT}% of core capacity)" echo "" echo " RAM Total: $MEM_TOTAL" echo " RAM Used: $MEM_USED (${MEM_PERCENT}%)" echo " RAM Available: $MEM_AVAILABLE" echo "" echo " Swap Total: $SWAP_TOTAL" echo " Swap Used: $SWAP_USED (${SWAP_PERCENT}%)" echo "" echo " Disk (/) Total: $DISK_ROOT_TOTAL" echo " Disk (/) Used: $DISK_ROOT_USED (${DISK_ROOT_PERCENT})" echo "" echo " Uptime: $UPTIME" echo "" # Paths echo -e "${BOLD}Important Paths:${NC}" echo " Log Directory: $SYS_LOG_DIR" echo " User Home Base: $SYS_USER_HOME_BASE" echo "" } ############################################################################# # INITIALIZE ALL DETECTION ############################################################################# initialize_system_detection() { # Create temp session directory create_temp_session # Run all detections detect_control_panel detect_os detect_web_server detect_database detect_php_versions detect_cloudflare detect_firewall get_system_resources # Mark as initialized export SYS_DETECTION_COMPLETE="yes" } # Export all functions for use in subshells and sourced scripts export -f detect_control_panel export -f detect_os export -f detect_web_server export -f detect_database export -f detect_php_versions export -f detect_cloudflare export -f detect_firewall export -f get_system_resources export -f show_system_info export -f initialize_system_detection # Auto-initialize if not already done (when sourced) if [ -z "${SYS_DETECTION_COMPLETE:-}" ]; then # Just run initialization - output suppression was breaking variable assignment initialize_system_detection fi