#!/bin/bash ################################################################################ # Plesk Validation Script # Purpose: Verify all assumptions about Plesk file system, commands, and paths # Run this on a real Plesk server to validate our refactoring ################################################################################ # Note: NOT using 'set -e' so script continues even if individual tests fail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" RESULTS_FILE="/tmp/plesk-validation-results.txt" # Color output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Counters PASS=0 FAIL=0 WARN=0 echo "=======================================================================" echo "PLESK VALIDATION SCRIPT" echo "=======================================================================" echo "This script will verify all assumptions about Plesk" echo "Results will be saved to: $RESULTS_FILE" echo "" echo "Started: $(date)" echo "=======================================================================" echo "" # Initialize results file cat > "$RESULTS_FILE" <> "$RESULTS_FILE" ((PASS++)) } test_fail() { echo -e "${RED}[FAIL]${NC} $1" echo "[FAIL] $1" >> "$RESULTS_FILE" ((FAIL++)) } test_warn() { echo -e "${YELLOW}[WARN]${NC} $1" echo "[WARN] $1" >> "$RESULTS_FILE" ((WARN++)) } test_info() { echo -e "${BLUE}[INFO]${NC} $1" echo "[INFO] $1" >> "$RESULTS_FILE" } section_header() { echo "" echo "=======================================================================" echo "$1" echo "=======================================================================" echo "" >> "$RESULTS_FILE" echo "=======================================================================" >> "$RESULTS_FILE" echo "$1" >> "$RESULTS_FILE" echo "=======================================================================" >> "$RESULTS_FILE" } ################################################################################ # TEST 1: Control Panel Detection ################################################################################ section_header "TEST 1: Control Panel Detection" if [ -d "/usr/local/psa" ]; then test_pass "Plesk installation directory exists: /usr/local/psa" else test_fail "Plesk installation directory NOT found: /usr/local/psa" fi if command -v plesk &> /dev/null; then test_pass "plesk command available" # Get Plesk version PLESK_VERSION=$(plesk version 2>/dev/null | head -1) test_info "Plesk version: $PLESK_VERSION" else test_fail "plesk command not available" fi ################################################################################ # TEST 2: File System Structure ################################################################################ section_header "TEST 2: File System Structure" # Check main vhosts directory if [ -d "/var/www/vhosts" ]; then test_pass "Main vhosts directory exists: /var/www/vhosts" # Find a test domain TEST_DOMAIN="" for domain_dir in /var/www/vhosts/*; do domain=$(basename "$domain_dir") # Skip system directories if [[ "$domain" != "system" ]] && [[ "$domain" != "default" ]] && [[ "$domain" != "chroot" ]] && [[ -d "$domain_dir/httpdocs" ]]; then TEST_DOMAIN="$domain" break fi done if [ -n "$TEST_DOMAIN" ]; then test_pass "Found test domain: $TEST_DOMAIN" # Test document root path EXPECTED_DOCROOT="/var/www/vhosts/$TEST_DOMAIN/httpdocs" if [ -d "$EXPECTED_DOCROOT" ]; then test_pass "Document root exists: $EXPECTED_DOCROOT" test_pass "VERIFIED: Document root pattern is /var/www/vhosts/DOMAIN/httpdocs" else test_fail "Document root NOT found: $EXPECTED_DOCROOT" fi # Test domain root structure test_info "Domain root structure for $TEST_DOMAIN:" ls -la "/var/www/vhosts/$TEST_DOMAIN" | head -20 >> "$RESULTS_FILE" 2>&1 else test_warn "No test domain found in /var/www/vhosts" test_info "Available directories:" ls -d /var/www/vhosts/*/ 2>/dev/null | head -10 >> "$RESULTS_FILE" fi else test_fail "Main vhosts directory NOT found: /var/www/vhosts" fi ################################################################################ # TEST 3: Log File Locations ################################################################################ section_header "TEST 3: Log File Locations" if [ -d "/var/www/vhosts/system" ]; then test_pass "System logs directory exists: /var/www/vhosts/system" if [ -n "$TEST_DOMAIN" ]; then # Test access log path EXPECTED_ACCESS_LOG="/var/www/vhosts/system/$TEST_DOMAIN/logs/access_log" if [ -f "$EXPECTED_ACCESS_LOG" ]; then test_pass "Access log exists: $EXPECTED_ACCESS_LOG" test_pass "VERIFIED: Access log pattern is /var/www/vhosts/system/DOMAIN/logs/access_log" else test_warn "Access log NOT found: $EXPECTED_ACCESS_LOG (may not have traffic yet)" fi # Test SSL access log path EXPECTED_SSL_LOG="/var/www/vhosts/system/$TEST_DOMAIN/logs/access_ssl_log" if [ -f "$EXPECTED_SSL_LOG" ]; then test_pass "SSL access log exists: $EXPECTED_SSL_LOG" else test_warn "SSL access log NOT found (may not have SSL traffic)" fi # Test error log path EXPECTED_ERROR_LOG="/var/www/vhosts/system/$TEST_DOMAIN/logs/error_log" if [ -f "$EXPECTED_ERROR_LOG" ]; then test_pass "Error log exists: $EXPECTED_ERROR_LOG" test_pass "VERIFIED: Error log pattern is /var/www/vhosts/system/DOMAIN/logs/error_log" else test_warn "Error log NOT found: $EXPECTED_ERROR_LOG (may not have errors yet)" fi # List all log files LOG_DIR="/var/www/vhosts/system/$TEST_DOMAIN/logs" if [ -d "$LOG_DIR" ]; then test_info "Log files found:" ls -lh "$LOG_DIR" >> "$RESULTS_FILE" 2>&1 fi fi else test_fail "System logs directory NOT found: /var/www/vhosts/system" fi # Check for domain-level error logs (PHP errors) if [ -n "$TEST_DOMAIN" ]; then PHP_ERROR_LOG="/var/www/vhosts/$TEST_DOMAIN/httpdocs/error_log" if [ -f "$PHP_ERROR_LOG" ]; then test_pass "PHP error log exists in httpdocs: $PHP_ERROR_LOG" else test_warn "PHP error log not found in httpdocs (may not have PHP errors)" fi fi ################################################################################ # TEST 4: Plesk bin Commands ################################################################################ section_header "TEST 4: Plesk bin Commands" if [ -d "/usr/local/psa/bin" ]; then test_pass "Plesk bin directory exists: /usr/local/psa/bin" test_info "Available Plesk bin commands:" ls /usr/local/psa/bin | head -20 >> "$RESULTS_FILE" else test_fail "Plesk bin directory NOT found" fi # Test subscription command if command -v plesk &> /dev/null; then if plesk bin subscription --help &> /dev/null; then test_pass "plesk bin subscription command available" else test_fail "plesk bin subscription command not working" fi fi ################################################################################ # TEST 5: Domain → User Mapping ################################################################################ section_header "TEST 5: Domain → User Mapping (Owner Lookup)" if [ -n "$TEST_DOMAIN" ]; then test_info "Testing domain→user lookup for: $TEST_DOMAIN" # Method: plesk bin subscription --info DOMAIN SUBSCRIPTION_INFO=$(plesk bin subscription --info "$TEST_DOMAIN" 2>/dev/null) if [ -n "$SUBSCRIPTION_INFO" ]; then test_pass "Successfully retrieved subscription info for $TEST_DOMAIN" # Look for Owner field - Plesk uses "Owner's contact name:" format # Example: "Owner's contact name: LW Support (admin)" -> extract "admin" OWNER=$(echo "$SUBSCRIPTION_INFO" | grep -i "^Owner's contact name:" | sed "s/^Owner's contact name:[[:space:]]*//" | grep -o '([^)]*)' | tr -d '()') if [ -n "$OWNER" ]; then test_pass "Found Owner's contact name field: $OWNER" test_pass "VERIFIED: Domain→User lookup works via: plesk bin subscription --info DOMAIN | grep \"Owner's contact name\"" TEST_OWNER="$OWNER" else # Try Login field as alternative OWNER=$(echo "$SUBSCRIPTION_INFO" | grep -i "^Login:" | awk '{print $2}') if [ -n "$OWNER" ]; then test_pass "Found Login field: $OWNER (alternative to Owner's contact name)" TEST_OWNER="$OWNER" else test_fail "Could not find Owner's contact name or Login field in subscription info" fi fi # Show sample output test_info "Sample subscription info output:" echo "$SUBSCRIPTION_INFO" | head -15 >> "$RESULTS_FILE" else test_fail "Could not retrieve subscription info for: $TEST_DOMAIN" fi else test_warn "No test domain available for lookup test" fi ################################################################################ # TEST 6: User → Domains Mapping ################################################################################ section_header "TEST 6: User → Domains Mapping (List User's Domains)" if [ -n "$TEST_OWNER" ]; then test_info "Testing user→domains lookup for owner: $TEST_OWNER" # Method 1: plesk bin subscription --list -owner USERNAME USER_DOMAINS=$(plesk bin subscription --list -owner "$TEST_OWNER" 2>/dev/null) if [ -n "$USER_DOMAINS" ]; then DOMAIN_COUNT=$(echo "$USER_DOMAINS" | wc -l) test_pass "Method 1: plesk bin subscription --list -owner found $DOMAIN_COUNT domain(s)" test_pass "VERIFIED: User→Domains lookup works via: plesk bin subscription --list -owner USERNAME" test_info "Domains for owner $TEST_OWNER:" echo "$USER_DOMAINS" >> "$RESULTS_FILE" else test_warn "Method 1: No domains found for owner $TEST_OWNER" fi # Method 2: From filesystem (alternative) FS_DOMAINS=$(find /var/www/vhosts -maxdepth 1 -type d ! -name "system" ! -name "default" ! -name "chroot" ! -name "vhosts" 2>/dev/null | xargs -n1 basename | sort) if [ -n "$FS_DOMAINS" ]; then FS_COUNT=$(echo "$FS_DOMAINS" | wc -l) test_info "Method 2: Found $FS_COUNT total domain(s) in filesystem (all users)" test_info "All domains in /var/www/vhosts:" echo "$FS_DOMAINS" | head -10 >> "$RESULTS_FILE" fi else test_warn "No test owner available - skipping user→domains test" fi ################################################################################ # TEST 7: Database Prefix Pattern ################################################################################ section_header "TEST 7: Database Prefix Pattern" test_info "Checking database naming conventions..." # Try to connect to MySQL/MariaDB if command -v mysql &> /dev/null; then # Try to get database list DB_LIST=$(mysql -e "SHOW DATABASES;" 2>/dev/null | grep -v "Database\|information_schema\|performance_schema\|mysql\|sys") if [ -n "$DB_LIST" ]; then test_pass "Successfully connected to database and retrieved database list" test_info "Sample databases:" echo "$DB_LIST" | head -15 >> "$RESULTS_FILE" # Check for prefix patterns HAS_UNDERSCORES=$(echo "$DB_LIST" | grep "_" | wc -l) NO_UNDERSCORES=$(echo "$DB_LIST" | grep -v "_" | wc -l) test_info "Databases with underscores: $HAS_UNDERSCORES" test_info "Databases without underscores: $NO_UNDERSCORES" # Check if databases follow username_ pattern or no prefix if [ "$NO_UNDERSCORES" -gt 0 ]; then test_info "Found databases without underscores (suggests NO PREFIX pattern)" test_info "Sample databases without prefix:" echo "$DB_LIST" | grep -v "_" | grep -v "test" | head -5 >> "$RESULTS_FILE" test_pass "DATABASE PREFIX PATTERN: Appears to use NO PREFIX (bare database names)" else test_warn "All databases have underscores - cannot determine prefix pattern" fi # Look for WordPress database pattern WP_DBS=$(echo "$DB_LIST" | grep -E "wp_|wordpress|_wp") if [ -n "$WP_DBS" ]; then test_info "Found WordPress-like databases:" echo "$WP_DBS" | head -5 >> "$RESULTS_FILE" fi else test_warn "Could not retrieve database list (may need credentials)" fi else test_warn "mysql command not found - cannot test database prefix" fi ################################################################################ # TEST 8: System User for Web Processes & File Ownership ################################################################################ section_header "TEST 8: System User for Web Processes & File Ownership" test_info "Checking what user runs web/PHP processes..." # Check PHP-FPM processes PHP_FPM_USERS=$(ps aux | grep "php-fpm" | grep -v "grep" | awk '{print $1}' | sort -u) if [ -n "$PHP_FPM_USERS" ]; then test_pass "Found PHP-FPM processes running as:" echo "$PHP_FPM_USERS" >> "$RESULTS_FILE" if echo "$PHP_FPM_USERS" | grep -q "www-data"; then test_info "PHP-FPM uses www-data (Debian/Ubuntu pattern)" WEB_USER="www-data" elif echo "$PHP_FPM_USERS" | grep -q "apache"; then test_info "PHP-FPM uses apache (RHEL/CentOS pattern)" WEB_USER="apache" else test_info "PHP-FPM uses custom user(s)" WEB_USER=$(echo "$PHP_FPM_USERS" | head -1) fi else test_warn "No PHP-FPM processes found" WEB_USER="www-data" # Default assumption fi # Check Apache processes APACHE_USERS=$(ps aux | grep -E "httpd|apache2" | grep -v "grep\|root" | awk '{print $1}' | sort -u | head -5) if [ -n "$APACHE_USERS" ]; then test_pass "Found Apache processes running as:" echo "$APACHE_USERS" >> "$RESULTS_FILE" else test_warn "No Apache processes found" fi # CRITICAL: Check file ownership of WordPress/web files if [ -n "$TEST_DOMAIN" ]; then DOCROOT="/var/www/vhosts/$TEST_DOMAIN/httpdocs" if [ -d "$DOCROOT" ]; then FILE_OWNER=$(stat -c '%U' "$DOCROOT" 2>/dev/null || stat -f '%Su' "$DOCROOT" 2>/dev/null) FILE_GROUP=$(stat -c '%G' "$DOCROOT" 2>/dev/null || stat -f '%Sg' "$DOCROOT" 2>/dev/null) if [ -n "$FILE_OWNER" ]; then test_pass "Document root owner: $FILE_OWNER:$FILE_GROUP" # Check if files are owned by web user or domain-specific user if [ "$FILE_OWNER" = "$WEB_USER" ]; then test_info "Files owned by web process user ($WEB_USER)" test_pass "ANSWER: Use 'crontab -u $WEB_USER' for cron jobs" CRON_USER="$WEB_USER" elif [ "$FILE_OWNER" = "$TEST_OWNER" ]; then test_info "Files owned by domain owner ($TEST_OWNER)" test_pass "ANSWER: Use 'crontab -u $TEST_OWNER' for cron jobs" CRON_USER="$TEST_OWNER" else test_warn "Files owned by different user: $FILE_OWNER (not web user or domain owner)" test_info "ANSWER: Use 'crontab -u $FILE_OWNER' for cron jobs" CRON_USER="$FILE_OWNER" fi # Test a sample file inside if [ -f "$DOCROOT/index.php" ] || [ -f "$DOCROOT/index.html" ]; then SAMPLE_FILE=$(find "$DOCROOT" -maxdepth 1 -type f -name "index.*" 2>/dev/null | head -1) if [ -n "$SAMPLE_FILE" ]; then SAMPLE_OWNER=$(stat -c '%U' "$SAMPLE_FILE" 2>/dev/null || stat -f '%Su' "$SAMPLE_FILE" 2>/dev/null) test_info "Sample file owner: $SAMPLE_OWNER (file: $(basename "$SAMPLE_FILE"))" fi fi else test_fail "Could not determine file ownership" fi fi fi ################################################################################ # TEST 9: Cron System (CRITICAL - Test Actual Operations!) ################################################################################ section_header "TEST 9: Cron System (CRITICAL - Test Actual Operations!)" if command -v crontab &> /dev/null; then test_pass "crontab command available" # Check for plesk bin cron command HAS_PLESK_CRON=0 if plesk bin cron --help &> /dev/null 2>&1; then test_pass "plesk bin cron command available (Plesk custom cron management)" HAS_PLESK_CRON=1 else test_info "plesk bin cron not available - using standard cron" fi # Check standard cron directory if [ -d "/var/spool/cron" ]; then test_pass "Standard cron spool directory exists: /var/spool/cron" test_info "Cron files found:" ls -lh /var/spool/cron/ 2>/dev/null >> "$RESULTS_FILE" elif [ -d "/var/spool/cron/crontabs" ]; then test_pass "Standard cron spool directory exists: /var/spool/cron/crontabs" test_info "Cron files found:" ls -lh /var/spool/cron/crontabs/ 2>/dev/null >> "$RESULTS_FILE" else test_warn "Standard cron spool directory not found" fi # CRITICAL TEST: Try to read/write cron for different users if [ -n "$CRON_USER" ]; then test_info "CRITICAL TEST: Testing cron operations for user: $CRON_USER" # Test 1: Can we read the crontab? if crontab -u "$CRON_USER" -l &> /dev/null; then test_pass "✓ CAN READ crontab for user: $CRON_USER" test_info "Current crontab entries:" crontab -u "$CRON_USER" -l 2>/dev/null >> "$RESULTS_FILE" else CRON_READ_ERR=$? if [ "$CRON_READ_ERR" -eq 1 ]; then test_info "User $CRON_USER has no crontab (this is OK - means empty)" else test_warn "Cannot read crontab for $CRON_USER (exit code: $CRON_READ_ERR)" fi fi # Test 2: Can we write a test cron entry? (ACTUALLY TEST IT) test_info "ATTEMPTING: Test cron write operation (will be immediately removed)..." # Backup existing crontab TEMP_BACKUP="/tmp/plesk_cron_backup_$$" crontab -u "$CRON_USER" -l > "$TEMP_BACKUP" 2>/dev/null || echo "# No existing crontab" > "$TEMP_BACKUP" # Try to add a test entry TEST_CRON_ENTRY="# TEST ENTRY - Plesk Validation - Will be removed" (crontab -u "$CRON_USER" -l 2>/dev/null; echo "$TEST_CRON_ENTRY") | crontab -u "$CRON_USER" - 2>/dev/null if [ $? -eq 0 ]; then test_pass "✓ CAN WRITE crontab for user: $CRON_USER" test_pass "ANSWER: Standard crontab works - use 'crontab -u $CRON_USER'" # Restore original crontab immediately crontab -u "$CRON_USER" "$TEMP_BACKUP" 2>/dev/null test_info "Test entry removed, original crontab restored" else test_fail "✗ CANNOT WRITE crontab for user: $CRON_USER" test_warn "May need to use 'plesk bin cron' instead of standard crontab" fi rm -f "$TEMP_BACKUP" fi # Test plesk bin cron if available if [ "$HAS_PLESK_CRON" -eq 1 ] && [ -n "$TEST_DOMAIN" ]; then test_info "Testing Plesk cron management for domain: $TEST_DOMAIN" # Try to list cron jobs via plesk PLESK_CRONS=$(plesk bin cron -l -domain "$TEST_DOMAIN" 2>/dev/null) if [ $? -eq 0 ]; then test_pass "✓ Can list Plesk cron jobs for domain" if [ -n "$PLESK_CRONS" ]; then test_info "Plesk cron jobs found:" echo "$PLESK_CRONS" | head -20 >> "$RESULTS_FILE" else test_info "No Plesk cron jobs configured for domain" fi else test_warn "Cannot list Plesk cron jobs (may need different syntax)" fi fi # Document which method to use echo "" >> "$RESULTS_FILE" echo "=== CRON MANAGEMENT CONCLUSION ===" >> "$RESULTS_FILE" if [ -n "$CRON_USER" ]; then echo "RECOMMENDED: Use standard crontab -u $CRON_USER for cron jobs" >> "$RESULTS_FILE" fi if [ "$HAS_PLESK_CRON" -eq 1 ]; then echo "ALTERNATIVE: Plesk bin cron available but may be for web UI management only" >> "$RESULTS_FILE" fi else test_fail "crontab command not available" fi ################################################################################ # TEST 10: PHP Configuration ################################################################################ section_header "TEST 10: PHP Configuration" # Check PHP versions test_info "Checking available PHP versions:" # Plesk-specific PHP locations if [ -d "/opt/plesk/php" ]; then test_pass "Plesk PHP directory exists: /opt/plesk/php" test_info "Plesk PHP versions:" ls -d /opt/plesk/php/*/ 2>/dev/null >> "$RESULTS_FILE" fi # System PHP versions PHP_BINS=$(find /usr/bin /opt -name "php" -o -name "php[0-9]*" 2>/dev/null | grep -E "php[0-9]|php$" | head -10) if [ -n "$PHP_BINS" ]; then test_info "Available PHP binaries:" echo "$PHP_BINS" >> "$RESULTS_FILE" fi # Check PHP-FPM pools if [ -d "/etc/php-fpm.d" ]; then test_pass "PHP-FPM pool directory exists: /etc/php-fpm.d" POOL_COUNT=$(ls /etc/php-fpm.d/*.conf 2>/dev/null | wc -l) test_info "Found $POOL_COUNT PHP-FPM pool config(s)" elif [ -d "/etc/php/*/fpm/pool.d" ]; then test_pass "PHP-FPM pool directory exists (Debian/Ubuntu pattern)" fi # Check how domain selects PHP version if [ -n "$TEST_DOMAIN" ]; then test_info "Checking PHP handler for $TEST_DOMAIN:" # Try plesk bin command PHP_HANDLER=$(plesk bin site -i "$TEST_DOMAIN" 2>/dev/null | grep -i "php") if [ -n "$PHP_HANDLER" ]; then test_pass "Retrieved PHP handler info via plesk bin site" echo "$PHP_HANDLER" >> "$RESULTS_FILE" else test_warn "Could not retrieve PHP handler info" fi fi ################################################################################ # TEST 11: WordPress Detection ################################################################################ section_header "TEST 11: WordPress Detection" test_info "Searching for WordPress installations..." WP_SITES=$(find /var/www/vhosts -maxdepth 3 -name "wp-config.php" -type f 2>/dev/null | head -10) if [ -n "$WP_SITES" ]; then WP_COUNT=$(echo "$WP_SITES" | wc -l) test_pass "Found $WP_COUNT WordPress installation(s)" # Test path pattern FIRST_WP=$(echo "$WP_SITES" | head -1) test_info "Sample WordPress path: $FIRST_WP" # Verify it matches expected pattern: /var/www/vhosts/DOMAIN/httpdocs/wp-config.php if echo "$FIRST_WP" | grep -qE "^/var/www/vhosts/[^/]+/httpdocs/wp-config.php$"; then test_pass "WordPress path matches expected pattern: /var/www/vhosts/DOMAIN/httpdocs/wp-config.php" test_pass "VERIFIED: WordPress detection pattern works" else test_warn "WordPress path doesn't match expected pattern (may be in subdirectory)" test_info "Actual pattern found: $FIRST_WP" fi # Extract domain from path WP_DOMAIN=$(echo "$FIRST_WP" | grep -oE '/vhosts/[^/]+' | sed 's|/vhosts/||') test_info "Extracted domain from path: $WP_DOMAIN" # Try to lookup owner WP_OWNER=$(plesk bin subscription --info "$WP_DOMAIN" 2>/dev/null | grep -i "^Owner:" | awk '{print $2}') if [ -n "$WP_OWNER" ]; then test_info "WordPress site owner: $WP_OWNER" fi else test_warn "No WordPress installations found (this is OK if none installed)" fi ################################################################################ # TEST 12: Apache/Web Server Configuration ################################################################################ section_header "TEST 12: Apache/Web Server Configuration" # Check Apache/httpd config if [ -d "/etc/httpd/conf.d" ]; then test_pass "Apache conf.d directory exists: /etc/httpd/conf.d" elif [ -d "/etc/apache2/sites-enabled" ]; then test_pass "Apache sites-enabled directory exists: /etc/apache2/sites-enabled" fi # Check for Plesk Apache configs if [ -d "/usr/local/psa/admin/conf" ]; then test_pass "Plesk admin conf directory exists" fi # Check if Apache or nginx if ps aux | grep -v grep | grep -q "nginx"; then test_info "System is using nginx" if ps aux | grep -v grep | grep -q "httpd\|apache"; then test_info "System is using nginx + Apache (Plesk typical setup)" fi elif ps aux | grep -v grep | grep -q "httpd\|apache"; then test_info "System is using Apache only" fi ################################################################################ # TEST 13: WordPress File Permissions & wp-config.php Access ################################################################################ section_header "TEST 13: WordPress File Permissions & wp-config.php Access" if [ -n "$FIRST_WP" ]; then test_info "Testing WordPress file access: $FIRST_WP" # Check if we can read wp-config.php if [ -r "$FIRST_WP" ]; then test_pass "✓ CAN READ wp-config.php as root" # Check file ownership WP_OWNER=$(stat -c '%U' "$FIRST_WP" 2>/dev/null || stat -f '%Su' "$FIRST_WP" 2>/dev/null) WP_PERMS=$(stat -c '%a' "$FIRST_WP" 2>/dev/null || stat -f '%Lp' "$FIRST_WP" 2>/dev/null) test_info "wp-config.php owner: $WP_OWNER" test_info "wp-config.php permissions: $WP_PERMS" # Try to extract database info DB_NAME=$(grep "DB_NAME" "$FIRST_WP" 2>/dev/null | head -1 | cut -d"'" -f4) DB_USER=$(grep "DB_USER" "$FIRST_WP" 2>/dev/null | head -1 | cut -d"'" -f4) if [ -n "$DB_NAME" ]; then test_pass "✓ Can extract database name: $DB_NAME" test_info "Database user: $DB_USER" # Check if DB name has prefix if echo "$DB_NAME" | grep -q "_"; then test_info "Database has underscore (may have prefix)" else test_info "Database has NO underscore (likely no prefix)" fi else test_warn "Could not extract database info from wp-config.php" fi else test_fail "✗ CANNOT READ wp-config.php (permission denied)" fi # Check WordPress installation directory WP_DIR=$(dirname "$FIRST_WP") test_info "WordPress directory: $WP_DIR" # List directory permissions WP_DIR_OWNER=$(stat -c '%U:%G' "$WP_DIR" 2>/dev/null || stat -f '%Su:%Sg' "$WP_DIR" 2>/dev/null) WP_DIR_PERMS=$(stat -c '%a' "$WP_DIR" 2>/dev/null || stat -f '%Lp' "$WP_DIR" 2>/dev/null) test_info "WordPress dir owner: $WP_DIR_OWNER" test_info "WordPress dir permissions: $WP_DIR_PERMS" fi ################################################################################ # TEST 14: Directory Structure Visualization ################################################################################ section_header "TEST 14: Directory Structure Visualization" test_info "Documenting directory structure for critical paths..." # Function to create a tree-like view (limited depth) create_tree() { local path="$1" local depth="${2:-2}" local prefix="${3:-}" if [ ! -d "$path" ]; then return fi # Use tree command if available, otherwise use find if command -v tree &> /dev/null; then tree -L "$depth" -F "$path" 2>/dev/null || find "$path" -maxdepth "$depth" -type d 2>/dev/null | head -50 else find "$path" -maxdepth "$depth" 2>/dev/null | head -50 | sed 's|[^/]*/| |g' fi } # Document domain directory structure if [ -n "$TEST_DOMAIN" ]; then echo "" >> "$RESULTS_FILE" echo "=== DOMAIN DIRECTORY STRUCTURE: $TEST_DOMAIN ===" >> "$RESULTS_FILE" echo "" >> "$RESULTS_FILE" test_info "Documenting domain structure for $TEST_DOMAIN..." DOMAIN_PATH="/var/www/vhosts/$TEST_DOMAIN" if [ -d "$DOMAIN_PATH" ]; then echo "Full path: $DOMAIN_PATH" >> "$RESULTS_FILE" echo "" >> "$RESULTS_FILE" create_tree "$DOMAIN_PATH" 3 >> "$RESULTS_FILE" 2>&1 fi # Document log directory structure echo "" >> "$RESULTS_FILE" echo "=== LOG DIRECTORY STRUCTURE: $TEST_DOMAIN ===" >> "$RESULTS_FILE" LOG_PATH="/var/www/vhosts/system/$TEST_DOMAIN" if [ -d "$LOG_PATH" ]; then echo "Full path: $LOG_PATH" >> "$RESULTS_FILE" echo "" >> "$RESULTS_FILE" create_tree "$LOG_PATH" 2 >> "$RESULTS_FILE" 2>&1 # List actual log files with sizes echo "" >> "$RESULTS_FILE" echo "Log files:" >> "$RESULTS_FILE" ls -lh "$LOG_PATH/logs/" 2>/dev/null >> "$RESULTS_FILE" fi fi # Document general vhosts structure echo "" >> "$RESULTS_FILE" echo "=== GENERAL VHOSTS STRUCTURE ===" >> "$RESULTS_FILE" test_info "Documenting /var/www/vhosts structure..." if [ -d "/var/www/vhosts" ]; then echo "Depth 1 view of /var/www/vhosts:" >> "$RESULTS_FILE" ls -lh /var/www/vhosts/ 2>/dev/null | head -20 >> "$RESULTS_FILE" # Show one sample domain structure SAMPLE_DOMAIN=$(find /var/www/vhosts -maxdepth 1 -type d ! -name "vhosts" ! -name "system" ! -name "default" 2>/dev/null | head -1) if [ -n "$SAMPLE_DOMAIN" ]; then echo "" >> "$RESULTS_FILE" echo "Sample domain structure: $(basename "$SAMPLE_DOMAIN")" >> "$RESULTS_FILE" create_tree "$SAMPLE_DOMAIN" 2 >> "$RESULTS_FILE" 2>&1 fi fi # Document Plesk directory structure echo "" >> "$RESULTS_FILE" echo "=== PLESK SYSTEM DIRECTORIES ===" >> "$RESULTS_FILE" test_info "Documenting Plesk system directories..." if [ -d "/usr/local/psa" ]; then echo "/usr/local/psa structure (depth 1):" >> "$RESULTS_FILE" ls -lh /usr/local/psa/ 2>/dev/null >> "$RESULTS_FILE" fi # Document PHP directory structure echo "" >> "$RESULTS_FILE" echo "=== PHP DIRECTORY STRUCTURE ===" >> "$RESULTS_FILE" if [ -d "/opt/plesk/php" ]; then echo "/opt/plesk/php structure:" >> "$RESULTS_FILE" create_tree "/opt/plesk/php" 2 >> "$RESULTS_FILE" 2>&1 fi ################################################################################ # TEST 15: Comprehensive System Documentation ################################################################################ section_header "TEST 15: Comprehensive System Documentation" test_info "Gathering complete system information for future reference..." # Document all Plesk binaries test_info "Cataloging Plesk bin commands..." if [ -d "/usr/local/psa/bin" ]; then echo "" >> "$RESULTS_FILE" echo "=== ALL PLESK BIN COMMANDS ===" >> "$RESULTS_FILE" ls -1 /usr/local/psa/bin >> "$RESULTS_FILE" fi # Document Plesk version info test_info "Documenting Plesk version details..." if command -v plesk &> /dev/null; then echo "" >> "$RESULTS_FILE" echo "=== PLESK VERSION DETAILS ===" >> "$RESULTS_FILE" plesk version 2>/dev/null >> "$RESULTS_FILE" fi # Document all domains on system test_info "Cataloging all domains on system..." ALL_DOMAINS=$(find /var/www/vhosts -maxdepth 1 -type d ! -name "vhosts" ! -name "system" ! -name "default" ! -name "chroot" 2>/dev/null | xargs -n1 basename | sort) if [ -n "$ALL_DOMAINS" ]; then DOMAIN_COUNT=$(echo "$ALL_DOMAINS" | wc -l) echo "" >> "$RESULTS_FILE" echo "=== ALL DOMAINS ON SYSTEM (Total: $DOMAIN_COUNT) ===" >> "$RESULTS_FILE" echo "$ALL_DOMAINS" >> "$RESULTS_FILE" fi # Document PHP versions available test_info "Documenting all PHP versions..." echo "" >> "$RESULTS_FILE" echo "=== PHP VERSIONS AVAILABLE ===" >> "$RESULTS_FILE" if [ -d "/opt/plesk/php" ]; then ls -1d /opt/plesk/php/*/ 2>/dev/null | xargs -n1 basename >> "$RESULTS_FILE" fi which php 2>/dev/null >> "$RESULTS_FILE" php -v 2>/dev/null | head -1 >> "$RESULTS_FILE" # Document Apache/nginx configuration test_info "Documenting web server setup..." echo "" >> "$RESULTS_FILE" echo "=== WEB SERVER CONFIGURATION ===" >> "$RESULTS_FILE" if ps aux | grep -v grep | grep -q "nginx"; then echo "nginx: RUNNING" >> "$RESULTS_FILE" nginx -v 2>&1 >> "$RESULTS_FILE" fi if ps aux | grep -v grep | grep -q "httpd\|apache"; then echo "Apache: RUNNING" >> "$RESULTS_FILE" httpd -v 2>&1 >> "$RESULTS_FILE" || apache2 -v 2>&1 >> "$RESULTS_FILE" fi # Document database server test_info "Documenting database server..." echo "" >> "$RESULTS_FILE" echo "=== DATABASE SERVER ===" >> "$RESULTS_FILE" if command -v mysql &> /dev/null; then mysql -V >> "$RESULTS_FILE" 2>&1 fi # Create a quick reference for developers echo "" >> "$RESULTS_FILE" echo "=======================================================================" >> "$RESULTS_FILE" echo "QUICK REFERENCE FOR DEVELOPERS" >> "$RESULTS_FILE" echo "=======================================================================" >> "$RESULTS_FILE" echo "" >> "$RESULTS_FILE" echo "Document roots: /var/www/vhosts/DOMAIN/httpdocs/" >> "$RESULTS_FILE" echo "Access logs: /var/www/vhosts/system/DOMAIN/logs/access_log" >> "$RESULTS_FILE" echo "Error logs: /var/www/vhosts/system/DOMAIN/logs/error_log" >> "$RESULTS_FILE" echo "WordPress: /var/www/vhosts/DOMAIN/httpdocs/wp-config.php" >> "$RESULTS_FILE" echo "" >> "$RESULTS_FILE" if [ -n "$CRON_USER" ]; then echo "Cron user: $CRON_USER" >> "$RESULTS_FILE" echo "Cron command: crontab -u $CRON_USER" >> "$RESULTS_FILE" fi if [ -n "$DB_NAME" ]; then echo "" >> "$RESULTS_FILE" echo "Sample database: $DB_NAME" >> "$RESULTS_FILE" if echo "$DB_NAME" | grep -q "_"; then echo "Database prefix: APPEARS TO HAVE PREFIX" >> "$RESULTS_FILE" else echo "Database prefix: APPEARS TO BE NO PREFIX" >> "$RESULTS_FILE" fi fi ################################################################################ # SUMMARY ################################################################################ section_header "VALIDATION SUMMARY" TOTAL=$((PASS + FAIL + WARN)) echo "" echo "=======================================================================" echo "RESULTS SUMMARY" echo "=======================================================================" echo -e "${GREEN}PASS: $PASS${NC}" echo -e "${RED}FAIL: $FAIL${NC}" echo -e "${YELLOW}WARN: $WARN${NC}" echo "TOTAL TESTS: $TOTAL" echo "" cat >> "$RESULTS_FILE" <> "$RESULTS_FILE" echo "" echo "Plesk validation successful!" echo "" echo "CRITICAL ANSWERS DISCOVERED:" if [ -n "$CRON_USER" ]; then echo " • Cron user: $CRON_USER" fi if [ -n "$DB_NAME" ]; then echo " • Database pattern: $(echo "$DB_NAME" | grep -q "_" && echo "HAS PREFIX" || echo "NO PREFIX")" fi if [ -n "$FILE_OWNER" ]; then echo " • File ownership: $FILE_OWNER" fi else echo -e "${RED}✗ SOME TESTS FAILED - REVIEW RESULTS${NC}" echo "✗ SOME TESTS FAILED - REVIEW RESULTS" >> "$RESULTS_FILE" fi echo "" echo "Full results saved to: $RESULTS_FILE" echo "" echo "=======================================================================" echo "NEXT STEPS:" echo "=======================================================================" echo "1. Review $RESULTS_FILE for complete details" echo "2. Report findings to development team" echo "3. Test actual toolkit modules if validation passed" echo "=======================================================================" exit 0