Add comprehensive automatic diagnostics for 500 errors
Added 10+ new automated checks that run when no PHP error is found in error_log: New checks added: 1. .htaccess issues: - Invalid PHP directives (php_value/php_flag with FPM) - Malformed RewriteRule syntax - Missing RewriteBase with relative paths 2. File validation: - File exists check (FILE_NOT_FOUND) - File readable check (PERMISSION_ERROR) - PHP syntax validation using php -l (PHP_SYNTAX_ERROR) 3. Directory permissions: - Document root exists (DOCROOT_MISSING) - Document root permissions (755/750/711) 4. PHP handler issues: - PHP handler configured for domain - .htaccess AddHandler/SetHandler misconfig (PHP_HANDLER_ERROR) 5. WordPress-specific: - wp-config.php readable - WP_DEBUG_DISPLAY causing 500s (WP_DEBUG_ERROR) Flow: When error_log has no matching errors, script now runs ALL checks sequentially until it finds an issue, providing specific diagnosis instead of generic "NO_PHP_ERROR_LOGGED". This should catch most common 500 error causes automatically. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -349,27 +349,118 @@ while IFS='|' read -r domain user status url timestamp ip; do
|
||||
((diagnosed_causes["$cause"]++))
|
||||
[ -z "${cause_examples[$cause]}" ] && cause_examples["$cause"]="$diagnosis"
|
||||
else
|
||||
# No matching error in error_log - check .htaccess as fallback
|
||||
if [ "$user" != "unknown" ] && [ -f "$docroot/.htaccess" ]; then
|
||||
htaccess_file="$docroot/.htaccess"
|
||||
htaccess_issues=""
|
||||
# No matching error in error_log - run comprehensive checks
|
||||
if [ "$user" != "unknown" ]; then
|
||||
issue_found=""
|
||||
|
||||
# Check for invalid PHP directives
|
||||
if grep -qE "^[[:space:]]*(php_value|php_flag|php_admin_value|php_admin_flag)" "$htaccess_file" 2>/dev/null; then
|
||||
if ! apache2ctl -M 2>/dev/null | grep -q "php.*module"; then
|
||||
htaccess_issues="PHP directives (php_value/php_flag) incompatible with current PHP handler (not mod_php)"
|
||||
# Check 1: .htaccess issues
|
||||
if [ -f "$docroot/.htaccess" ]; then
|
||||
htaccess_file="$docroot/.htaccess"
|
||||
htaccess_issues=""
|
||||
|
||||
# Invalid PHP directives
|
||||
if grep -qE "^[[:space:]]*(php_value|php_flag|php_admin_value|php_admin_flag)" "$htaccess_file" 2>/dev/null; then
|
||||
if ! apache2ctl -M 2>/dev/null | grep -q "php.*module"; then
|
||||
htaccess_issues="PHP directives incompatible with FPM"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Malformed RewriteRule
|
||||
bad_rewrite=$(grep -nE "RewriteRule.*\[.*[^]]*$" "$htaccess_file" 2>/dev/null | head -1)
|
||||
[ -n "$bad_rewrite" ] && htaccess_issues="${htaccess_issues:+$htaccess_issues; }Malformed RewriteRule: ${bad_rewrite:0:50}"
|
||||
|
||||
# Missing RewriteBase with RewriteRule
|
||||
if grep -q "RewriteRule" "$htaccess_file" 2>/dev/null; then
|
||||
if ! grep -q "RewriteBase" "$htaccess_file" 2>/dev/null; then
|
||||
# Check if rules use relative paths
|
||||
if grep -qE "RewriteRule.*\^[^/]" "$htaccess_file" 2>/dev/null; then
|
||||
htaccess_issues="${htaccess_issues:+$htaccess_issues; }Missing RewriteBase with relative paths"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$htaccess_issues" ]; then
|
||||
cause="HTACCESS_ERROR"
|
||||
diagnosis="$domain$url - $htaccess_issues"
|
||||
issue_found="yes"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check for malformed RewriteRule
|
||||
bad_rewrite=$(grep -nE "RewriteRule.*\[.*[^]]*$" "$htaccess_file" 2>/dev/null | head -1)
|
||||
if [ -n "$bad_rewrite" ]; then
|
||||
htaccess_issues="${htaccess_issues:+$htaccess_issues; }Malformed RewriteRule: $bad_rewrite"
|
||||
# Check 2: PHP file exists and is readable
|
||||
if [ -z "$issue_found" ] && [ -n "$specific_file" ]; then
|
||||
if [ ! -f "$specific_file" ]; then
|
||||
cause="FILE_NOT_FOUND"
|
||||
diagnosis="$domain$url - File does not exist: $specific_file"
|
||||
issue_found="yes"
|
||||
elif [ ! -r "$specific_file" ]; then
|
||||
file_perms=$(stat -c "%a" "$specific_file" 2>/dev/null)
|
||||
cause="PERMISSION_ERROR"
|
||||
diagnosis="$domain$url - File not readable: $specific_file (perms: $file_perms)"
|
||||
issue_found="yes"
|
||||
else
|
||||
# Check for PHP syntax errors
|
||||
syntax_check=$(php -l "$specific_file" 2>&1)
|
||||
if [[ "$syntax_check" =~ "Parse error" ]] || [[ "$syntax_check" =~ "syntax error" ]]; then
|
||||
cause="PHP_SYNTAX_ERROR"
|
||||
syntax_line=$(echo "$syntax_check" | grep -oP "line \K[0-9]+" | head -1)
|
||||
diagnosis="$domain$url - PHP syntax error in $specific_file${syntax_line:+ at line $syntax_line}"
|
||||
issue_found="yes"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$htaccess_issues" ]; then
|
||||
cause="HTACCESS_ERROR"
|
||||
diagnosis="$domain$url - .htaccess error: $htaccess_issues"
|
||||
# Check 3: Document root permissions
|
||||
if [ -z "$issue_found" ]; then
|
||||
if [ ! -d "$docroot" ]; then
|
||||
cause="DOCROOT_MISSING"
|
||||
diagnosis="$domain$url - Document root does not exist: $docroot"
|
||||
issue_found="yes"
|
||||
else
|
||||
docroot_perms=$(stat -c "%a" "$docroot" 2>/dev/null)
|
||||
if [ "$docroot_perms" != "755" ] && [ "$docroot_perms" != "750" ] && [ "$docroot_perms" != "711" ]; then
|
||||
cause="PERMISSION_ERROR"
|
||||
diagnosis="$domain$url - Docroot bad perms: $docroot ($docroot_perms, should be 755)"
|
||||
issue_found="yes"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check 4: PHP handler/version issues
|
||||
if [ -z "$issue_found" ] && [ -n "$specific_file" ] && [ -f "$specific_file" ]; then
|
||||
# Check if PHP is configured for this domain
|
||||
php_handler=$(grep -i "phpversion\|php_admin_value" /var/cpanel/userdata/$user/$domain 2>/dev/null | head -1)
|
||||
if [ -z "$php_handler" ]; then
|
||||
# Check if .htaccess tries to set PHP version but fails
|
||||
if grep -qE "AddHandler.*php|SetHandler.*php" "$docroot/.htaccess" 2>/dev/null; then
|
||||
cause="PHP_HANDLER_ERROR"
|
||||
diagnosis="$domain$url - PHP handler misconfigured (check .htaccess AddHandler/SetHandler)"
|
||||
issue_found="yes"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check 5: WordPress-specific issues (if WP detected)
|
||||
if [ -z "$issue_found" ] && [ -f "$docroot/wp-config.php" ]; then
|
||||
# Check if wp-config.php is readable
|
||||
if [ ! -r "$docroot/wp-config.php" ]; then
|
||||
cause="PERMISSION_ERROR"
|
||||
diagnosis="$domain$url - wp-config.php not readable"
|
||||
issue_found="yes"
|
||||
else
|
||||
# Check for WP_DEBUG causing issues
|
||||
if grep -q "define.*WP_DEBUG.*true" "$docroot/wp-config.php" 2>/dev/null; then
|
||||
# Check if WP_DEBUG_DISPLAY is also true (can cause 500s with some errors)
|
||||
if grep -q "define.*WP_DEBUG_DISPLAY.*true" "$docroot/wp-config.php" 2>/dev/null; then
|
||||
cause="WP_DEBUG_ERROR"
|
||||
diagnosis="$domain$url - WP_DEBUG_DISPLAY enabled (may cause 500 on warnings)"
|
||||
issue_found="yes"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Save diagnosis if we found an issue
|
||||
if [ -n "$issue_found" ] && [ -n "$diagnosis" ]; then
|
||||
echo "$cause|$diagnosis" >> "$DETAILED_DIAGNOSIS"
|
||||
((diagnosed_causes["$cause"]++))
|
||||
[ -z "${cause_examples[$cause]}" ] && cause_examples["$cause"]="$diagnosis"
|
||||
@@ -593,6 +684,22 @@ done | sort -rn | while IFS='|' read count cause; do
|
||||
echo -e "${YELLOW}$clean_cause${NC} - $count occurrences"
|
||||
echo -e " ${YELLOW}Note:${NC} 500 error but no PHP error in log - likely .htaccess or Apache config"
|
||||
;;
|
||||
FILE_NOT_FOUND)
|
||||
echo -e "${RED}$clean_cause${NC} - $count occurrences"
|
||||
echo -e " ${YELLOW}Fix:${NC} Requested file does not exist - check URL or restore missing files"
|
||||
;;
|
||||
PHP_HANDLER_ERROR)
|
||||
echo -e "${RED}PHP HANDLER ERROR${NC} - $count occurrences"
|
||||
echo -e " ${YELLOW}Fix:${NC} PHP handler misconfigured - check cPanel PHP version or .htaccess AddHandler"
|
||||
;;
|
||||
WP_DEBUG_ERROR)
|
||||
echo -e "${YELLOW}WORDPRESS DEBUG ERROR${NC} - $count occurrences"
|
||||
echo -e " ${YELLOW}Fix:${NC} Disable WP_DEBUG_DISPLAY in wp-config.php or fix underlying warnings"
|
||||
;;
|
||||
DOCROOT_MISSING)
|
||||
echo -e "${RED}$clean_cause${NC} - $count occurrences"
|
||||
echo -e " ${YELLOW}Fix:${NC} Document root directory missing - restore from backup or check domain configuration"
|
||||
;;
|
||||
UNKNOWN)
|
||||
# Skip - these are errors we couldn't diagnose
|
||||
;;
|
||||
@@ -632,7 +739,7 @@ echo ""
|
||||
|
||||
# Show detailed diagnostics grouped by cause - deduplicate by domain+url+issue
|
||||
if [ -f "$DETAILED_DIAGNOSIS" ] && [ -s "$DETAILED_DIAGNOSIS" ]; then
|
||||
for cause_type in PHP_MEMORY_EXHAUSTED PERMISSION_ERROR HTACCESS_ERROR PHP_FATAL_ERROR PHP_SYNTAX_ERROR MISSING_PHP_FUNCTION DATABASE_CONNECTION; do
|
||||
for cause_type in PHP_MEMORY_EXHAUSTED PERMISSION_ERROR HTACCESS_ERROR PHP_FATAL_ERROR PHP_SYNTAX_ERROR MISSING_PHP_FUNCTION DATABASE_CONNECTION FILE_NOT_FOUND PHP_HANDLER_ERROR WP_DEBUG_ERROR DOCROOT_MISSING; do
|
||||
# Get unique diagnostics (deduplicate identical domain+issue combinations)
|
||||
unique_diags=$(grep "^${cause_type}|" "$DETAILED_DIAGNOSIS" 2>/dev/null | cut -d'|' -f2 | sort -u)
|
||||
cause_count=$(echo "$unique_diags" | grep -c "^" 2>/dev/null || echo "0")
|
||||
|
||||
Reference in New Issue
Block a user