diff --git a/modules/website/website-error-analyzer.sh b/modules/website/website-error-analyzer.sh index d64a142..ed359a6 100755 --- a/modules/website/website-error-analyzer.sh +++ b/modules/website/website-error-analyzer.sh @@ -190,96 +190,69 @@ echo "" is_noise() { local line="$1" + local line_lower="${line,,}" # Convert to lowercase once # Bot/Scanner patterns - if echo "$line" | grep -qiE "bot|crawler|spider|scanner|nikto|nmap|masscan|sqlmap|nessus|acunetix|burp|shodan|censys|zgrab|nuclei|semrush|ahrefs|mj12"; then - return 0 - fi + [[ "$line_lower" =~ (bot|crawler|spider|scanner|nikto|nmap|masscan|sqlmap|nessus|acunetix|burp|shodan|censys|zgrab|nuclei|semrush|ahrefs|mj12) ]] && return 0 # Known scanner IPs - if echo "$line" | grep -qE "45\.148\.|185\.220\.|89\.248\.165\."; then - return 0 - fi + [[ "$line" =~ (45\.148\.|185\.220\.|89\.248\.165\.) ]] && return 0 # WordPress plugin deprecation warnings (not user-facing) - if echo "$line" | grep -qiE "PHP Deprecated|Deprecated.*plugin|call_user_func_array.*deprecated"; then - return 0 - fi + [[ "$line" =~ (PHP\ Deprecated|Deprecated.*plugin|call_user_func_array.*deprecated) ]] && return 0 - # Non-critical PHP notices - if echo "$line" | grep -qiE "PHP Notice.*Undefined (variable|index|offset)" && \ - ! echo "$line" | grep -qiE "fatal|error 500|white screen"; then + # Non-critical PHP notices (unless critical indicators present) + if [[ "$line" =~ PHP\ Notice.*Undefined\ (variable|index|offset) ]] && ! [[ "$line_lower" =~ (fatal|error\ 500|white\ screen) ]]; then return 0 fi # Missing favicon/common assets (not real errors) - if echo "$line" | grep -qiE "favicon\.ico|apple-touch-icon|robots\.txt|sitemap\.xml.*404"; then - return 0 - fi + [[ "$line_lower" =~ (favicon\.ico|apple-touch-icon|robots\.txt|sitemap\.xml.*404) ]] && return 0 # Security probes - if echo "$line" | grep -qiE "wp-admin|wp-login|phpMyAdmin|phpmyadmin|\.env|\.git|config\.php|xmlrpc|eval-stdin|shell\.php|c99\.php|r57\.php|adminer\.php" && \ - echo "$line" | grep -qiE "404|403|not found"; then + if [[ "$line_lower" =~ (wp-admin|wp-login|phpmyadmin|\.env|\.git|config\.php|xmlrpc|eval-stdin|shell\.php|c99\.php|r57\.php|adminer\.php) ]] && \ + [[ "$line" =~ (404|403|not\ found) ]]; then return 0 fi # WordPress auto-updates and cron (normal operations) - if echo "$line" | grep -qiE "wp-cron\.php|doing_cron|auto.*update"; then - return 0 - fi + [[ "$line_lower" =~ (wp-cron\.php|doing_cron|auto.*update) ]] && return 0 # Common plugin update checks (not errors) - if echo "$line" | grep -qiE "update-check|version-check|api\.wordpress\.org"; then - return 0 - fi + [[ "$line_lower" =~ (update-check|version-check|api\.wordpress\.org) ]] && return 0 return 1 } is_critical_user_facing() { local line="$1" + local line_lower="${line,,}" # 500 Internal Server Error (users see white page) - if echo "$line" | grep -qiE " 500 |Internal Server Error"; then - return 0 - fi + [[ "$line" =~ (\ 500\ |Internal\ Server\ Error) ]] && return 0 # PHP Fatal Errors (breaks functionality) - if echo "$line" | grep -qiE "PHP Fatal error|Fatal error:.*in /"; then - return 0 - fi + [[ "$line" =~ (PHP\ Fatal\ error|Fatal\ error:.*in\ /) ]] && return 0 # PHP Parse Errors (site completely broken) - if echo "$line" | grep -qiE "PHP Parse error|syntax error"; then - return 0 - fi + [[ "$line" =~ (PHP\ Parse\ error|syntax\ error) ]] && return 0 # Database connection failures (site down) - if echo "$line" | grep -qiE "Error establishing.*database|Can't connect.*MySQL|Access denied for user.*database|Too many connections|MySQL server has gone away"; then - return 0 - fi + [[ "$line" =~ (Error\ establishing.*database|Can\'t\ connect.*MySQL|Access\ denied\ for\ user.*database|Too\ many\ connections|MySQL\ server\ has\ gone\ away) ]] && return 0 # Memory exhaustion (white screen/incomplete pages) - if echo "$line" | grep -qiE "Allowed memory size.*exhausted|Out of memory|Fatal.*memory"; then - return 0 - fi + [[ "$line" =~ (Allowed\ memory\ size.*exhausted|Out\ of\ memory|Fatal.*memory) ]] && return 0 # Segmentation fault (complete crash) - if echo "$line" | grep -qiE "Segmentation fault|signal 11"; then - return 0 - fi + [[ "$line" =~ (Segmentation\ fault|signal\ 11) ]] && return 0 # Permission denied on critical files - if echo "$line" | grep -qiE "Permission denied" && \ - echo "$line" | grep -qE "index\.php|wp-config\.php|\.htaccess|config\.php"; then + if [[ "$line" =~ Permission\ denied ]] && [[ "$line" =~ (index\.php|wp-config\.php|\.htaccess|config\.php) ]]; then return 0 fi # File not found for MAIN page (404 on homepage/index) - if echo "$line" | grep -qiE "File does not exist.*index\.(php|html)" || \ - echo "$line" | grep -qE " 404 .*\" \"GET / "; then - return 0 - fi + [[ "$line" =~ (File\ does\ not\ exist.*index\.(php|html)|\ 404\ .*\"\ \"GET\ /) ]] && return 0 return 1 } @@ -321,17 +294,19 @@ correlate_root_cause() { local error_msg="$2" local domain="$3" local cause="UNKNOWN" + local line_lower="${line,,}" + local error_lower="${error_msg,,}" # .htaccess issues - if echo "$line" | grep -qiE "\.htaccess|Invalid command|RewriteRule|RewriteCond"; then + if [[ "$line_lower" =~ (\.htaccess|invalid\ command|rewriterule|rewritecond) ]]; then cause="HTACCESS" # ModSecurity blocks - elif echo "$line" | grep -qiE "ModSecurity|mod_security|WAF"; then + elif [[ "$line_lower" =~ (modsecurity|mod_security|waf) ]]; then cause="MODSECURITY" # PHP memory limit - elif echo "$error_msg" | grep -qiE "memory.*exhausted|Allowed memory size"; then + elif [[ "$error_lower" =~ (memory.*exhausted|allowed\ memory\ size) ]]; then # Get current memory limit for this domain/user if [ -n "$domain" ] && [ "$domain" != "unknown" ]; then user=$(grep -l "DNS.*$domain" /var/cpanel/users/* 2>/dev/null | head -1 | xargs basename 2>/dev/null) @@ -346,62 +321,62 @@ correlate_root_cause() { fi # PHP max execution time - elif echo "$error_msg" | grep -qiE "max_execution_time|Maximum execution time"; then + elif [[ "$error_lower" =~ (max_execution_time|maximum\ execution\ time) ]]; then cause="PHP_TIMEOUT" # PHP upload/post size limits - elif echo "$error_msg" | grep -qiE "upload_max_filesize|post_max_size"; then + elif [[ "$error_lower" =~ (upload_max_filesize|post_max_size) ]]; then cause="PHP_UPLOAD_LIMIT" # File permissions - elif echo "$error_msg" | grep -qiE "Permission denied|Failed to open stream.*permission"; then + elif [[ "$error_lower" =~ (permission\ denied|failed\ to\ open\ stream.*permission) ]]; then cause="FILE_PERMISSIONS" # Missing PHP modules/extensions - elif echo "$error_msg" | grep -qiE "undefined function|Call to undefined function|Class .* not found"; then + elif [[ "$error_lower" =~ (undefined\ function|call\ to\ undefined\ function|class\ .*\ not\ found) ]]; then # Try to identify which module - if echo "$error_msg" | grep -qiE "imagecreate|imagefilter|gd_"; then + if [[ "$error_lower" =~ (imagecreate|imagefilter|gd_) ]]; then cause="MISSING_PHP_GD" - elif echo "$error_msg" | grep -qiE "curl_|CURL"; then + elif [[ "$error_msg" =~ (curl_|CURL) ]]; then cause="MISSING_PHP_CURL" - elif echo "$error_msg" | grep -qiE "json_|JSON"; then + elif [[ "$error_msg" =~ (json_|JSON) ]]; then cause="MISSING_PHP_JSON" - elif echo "$error_msg" | grep -qiE "mysqli|mysql_connect"; then + elif [[ "$error_lower" =~ (mysqli|mysql_connect) ]]; then cause="MISSING_PHP_MYSQLI" else cause="MISSING_PHP_MODULE" fi # Database issues - elif echo "$error_msg" | grep -qiE "database|MySQL|mysqli"; then - if echo "$error_msg" | grep -qiE "Too many connections|max_connections"; then + elif [[ "$error_lower" =~ (database|mysql|mysqli) ]]; then + if [[ "$error_lower" =~ (too\ many\ connections|max_connections) ]]; then cause="DB_MAX_CONNECTIONS" - elif echo "$error_msg" | grep -qiE "Access denied|authentication"; then + elif [[ "$error_lower" =~ (access\ denied|authentication) ]]; then cause="DB_AUTH_FAILED" - elif echo "$error_msg" | grep -qiE "gone away|Lost connection"; then + elif [[ "$error_lower" =~ (gone\ away|lost\ connection) ]]; then cause="DB_TIMEOUT" else cause="DB_ERROR" fi # Apache configuration - elif echo "$error_msg" | grep -qiE "Invalid URI|Request exceeded the limit|LimitRequestLine"; then + elif [[ "$error_lower" =~ (invalid\ uri|request\ exceeded\ the\ limit|limitrequestline) ]]; then cause="APACHE_CONFIG" # PHP parse/syntax errors (code issues) - elif echo "$error_msg" | grep -qiE "Parse error|syntax error|unexpected"; then + elif [[ "$error_lower" =~ (parse\ error|syntax\ error|unexpected) ]]; then cause="PHP_SYNTAX_ERROR" # File not found (may indicate bad symlinks or missing files) - elif echo "$error_msg" | grep -qiE "No such file|failed to open stream"; then + elif [[ "$error_lower" =~ (no\ such\ file|failed\ to\ open\ stream) ]]; then cause="MISSING_FILE" # Generic PHP fatal error - elif echo "$error_msg" | grep -qiE "Fatal error"; then + elif [[ "$error_lower" =~ fatal\ error ]]; then cause="PHP_FATAL_ERROR" # 500 errors without specific cause - elif echo "$error_msg" | grep -qiE "500|Internal Server"; then + elif [[ "$error_msg" =~ (500|Internal\ Server) ]]; then cause="SERVER_ERROR_500" fi