Add Fast 500 Error Tracker + Fix awk error in analyzer
NEW SCRIPT: modules/website/500-error-tracker.sh - FAST-ONLY 500 error detection (no menus, no options) - Scans access logs for 500 errors - Maps domains to cPanel usernames - Automatically diagnoses root causes by checking error_log files - Shows actual PHP errors causing the 500s ROOT CAUSE DETECTION: - PHP Memory Exhausted (shows current limit) - PHP Fatal Errors - PHP Syntax Errors - Missing PHP Functions/Extensions - Database Connection Failures - .htaccess Issues - Shows ACTUAL error examples, not just suggestions FIXES: - Fixed awk error in website-error-analyzer.sh: • Changed "next" in END block to "if (length > 0)" • "next" cannot be used in END block in awk - Added option 2 in Website Management menu - Renumbered all WordPress tools (3-16) DIFFERENCE FROM FULL ANALYZER: Full Analyzer: All errors, filters, time ranges, user choices Fast Tracker: ONLY 500s, auto-diagnosis, shows WHY not suggestions Use Fast Tracker when you need to quickly find which domains are getting 500 errors and the exact PHP errors causing them. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+30
-28
@@ -435,23 +435,24 @@ show_wordpress_menu() {
|
|||||||
echo -e "${BOLD}General Website Tools:${NC}"
|
echo -e "${BOLD}General Website Tools:${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e " ${BLUE}1)${NC} 🔍 Website Error Analyzer - Find 500/config errors (filters bots)"
|
echo -e " ${BLUE}1)${NC} 🔍 Website Error Analyzer - Find 500/config errors (filters bots)"
|
||||||
|
echo -e " ${RED}2)${NC} 🔥 Fast 500 Error Tracker - ONLY 500s + root cause diagnosis"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${BOLD}WordPress Tools:${NC}"
|
echo -e "${BOLD}WordPress Tools:${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e " ${BLUE}2)${NC} Health Check (All Sites) - Scan all WP installations"
|
echo -e " ${BLUE}3)${NC} Health Check (All Sites) - Scan all WP installations"
|
||||||
echo -e " ${BLUE}3)${NC} WP-Cron Status - Check cron job status"
|
echo -e " ${BLUE}4)${NC} WP-Cron Status - Check cron job status"
|
||||||
echo -e " ${BLUE}4)${NC} WP-Cron Mass Fix - Fix/enable cron on all sites"
|
echo -e " ${BLUE}5)${NC} WP-Cron Mass Fix - Fix/enable cron on all sites"
|
||||||
echo -e " ${BLUE}5)${NC} WP-Cron Mass Create - Setup proper system crons"
|
echo -e " ${BLUE}6)${NC} WP-Cron Mass Create - Setup proper system crons"
|
||||||
echo -e " ${BLUE}6)${NC} Plugin Audit - Security scan of plugins"
|
echo -e " ${BLUE}7)${NC} Plugin Audit - Security scan of plugins"
|
||||||
echo -e " ${BLUE}7)${NC} Theme Audit - Security scan of themes"
|
echo -e " ${BLUE}8)${NC} Theme Audit - Security scan of themes"
|
||||||
echo -e " ${BLUE}8)${NC} Database Optimizer - Clean/optimize WP databases"
|
echo -e " ${BLUE}9)${NC} Database Optimizer - Clean/optimize WP databases"
|
||||||
echo -e " ${BLUE}9)${NC} Cache Clear (All Sites) - Clear all WP caches"
|
echo -e " ${BLUE}10)${NC} Cache Clear (All Sites) - Clear all WP caches"
|
||||||
echo -e " ${BLUE}10)${NC} Mass Update Core - Update WordPress core (all)"
|
echo -e " ${BLUE}11)${NC} Mass Update Core - Update WordPress core (all)"
|
||||||
echo -e " ${BLUE}11)${NC} Mass Update Plugins - Update plugins (all sites)"
|
echo -e " ${BLUE}12)${NC} Mass Update Plugins - Update plugins (all sites)"
|
||||||
echo -e " ${BLUE}12)${NC} Login Security Audit - Check for weak passwords"
|
echo -e " ${BLUE}13)${NC} Login Security Audit - Check for weak passwords"
|
||||||
echo -e " ${BLUE}13)${NC} Malware Scanner - Scan for infected files"
|
echo -e " ${BLUE}14)${NC} Malware Scanner - Scan for infected files"
|
||||||
echo -e " ${BLUE}14)${NC} Permission Fixer - Fix file permissions"
|
echo -e " ${BLUE}15)${NC} Permission Fixer - Fix file permissions"
|
||||||
echo -e " ${BLUE}15)${NC} Debug Log Analyzer - Parse WP debug logs"
|
echo -e " ${BLUE}16)${NC} Debug Log Analyzer - Parse WP debug logs"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e " ${RED}0)${NC} Back to Main Menu"
|
echo -e " ${RED}0)${NC} Back to Main Menu"
|
||||||
echo ""
|
echo ""
|
||||||
@@ -1148,20 +1149,21 @@ handle_wordpress_menu() {
|
|||||||
|
|
||||||
case $choice in
|
case $choice in
|
||||||
1) run_module "website" "website-error-analyzer.sh" ;;
|
1) run_module "website" "website-error-analyzer.sh" ;;
|
||||||
2) run_module "wordpress" "wp-health-check.sh" ;;
|
2) run_module "website" "500-error-tracker.sh" ;;
|
||||||
3) run_module "wordpress" "wp-cron-status.sh" ;;
|
3) run_module "wordpress" "wp-health-check.sh" ;;
|
||||||
4) run_module "wordpress" "wp-cron-mass-fix.sh" ;;
|
4) run_module "wordpress" "wp-cron-status.sh" ;;
|
||||||
5) run_module "wordpress" "wp-cron-mass-create.sh" ;;
|
5) run_module "wordpress" "wp-cron-mass-fix.sh" ;;
|
||||||
6) run_module "wordpress" "wp-plugin-audit.sh" ;;
|
6) run_module "wordpress" "wp-cron-mass-create.sh" ;;
|
||||||
7) run_module "wordpress" "wp-theme-audit.sh" ;;
|
7) run_module "wordpress" "wp-plugin-audit.sh" ;;
|
||||||
8) run_module "wordpress" "wp-db-optimizer.sh" ;;
|
8) run_module "wordpress" "wp-theme-audit.sh" ;;
|
||||||
9) run_module "wordpress" "wp-cache-clear.sh" ;;
|
9) run_module "wordpress" "wp-db-optimizer.sh" ;;
|
||||||
10) run_module "wordpress" "wp-mass-update-core.sh" ;;
|
10) run_module "wordpress" "wp-cache-clear.sh" ;;
|
||||||
11) run_module "wordpress" "wp-mass-update-plugins.sh" ;;
|
11) run_module "wordpress" "wp-mass-update-core.sh" ;;
|
||||||
12) run_module "wordpress" "wp-login-security.sh" ;;
|
12) run_module "wordpress" "wp-mass-update-plugins.sh" ;;
|
||||||
13) run_module "wordpress" "wp-malware-scanner.sh" ;;
|
13) run_module "wordpress" "wp-login-security.sh" ;;
|
||||||
14) run_module "wordpress" "wp-permission-fixer.sh" ;;
|
14) run_module "wordpress" "wp-malware-scanner.sh" ;;
|
||||||
15) run_module "wordpress" "wp-debug-log-analyzer.sh" ;;
|
15) run_module "wordpress" "wp-permission-fixer.sh" ;;
|
||||||
|
16) run_module "wordpress" "wp-debug-log-analyzer.sh" ;;
|
||||||
0) return ;;
|
0) return ;;
|
||||||
*) echo -e "${RED}Invalid option${NC}"; sleep 1 ;;
|
*) echo -e "${RED}Invalid option${NC}"; sleep 1 ;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
Executable
+245
@@ -0,0 +1,245 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Fast 500 Error Tracker
|
||||||
|
################################################################################
|
||||||
|
# Purpose: ONLY track 500 errors - find them fast and show WHY
|
||||||
|
# No menus, no options - just find 500s and diagnose the root cause
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||||
|
source "$SCRIPT_DIR/lib/common-functions.sh"
|
||||||
|
|
||||||
|
print_banner "Fast 500 Error Tracker"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Scanning for 500 errors and diagnosing root causes..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Temporary files
|
||||||
|
TEMP_DIR="/tmp/500-tracker-$$"
|
||||||
|
mkdir -p "$TEMP_DIR"
|
||||||
|
trap "rm -rf $TEMP_DIR" EXIT
|
||||||
|
|
||||||
|
ERRORS_500="$TEMP_DIR/errors_500.txt"
|
||||||
|
ERROR_DETAILS="$TEMP_DIR/error_details.txt"
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
DOMLOGS_DIR="/var/log/apache2/domlogs"
|
||||||
|
HOURS_TO_SCAN=24
|
||||||
|
|
||||||
|
echo "→ Scanning last $HOURS_TO_SCAN hours of access logs..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Get cutoff time
|
||||||
|
cutoff_time=$(date -d "$HOURS_TO_SCAN hours ago" +%s 2>/dev/null || echo "0")
|
||||||
|
|
||||||
|
declare -A domain_count
|
||||||
|
declare -A domain_user
|
||||||
|
total_500s=0
|
||||||
|
|
||||||
|
# Scan all domain access logs for 500 errors
|
||||||
|
for log in "$DOMLOGS_DIR"/*; do
|
||||||
|
[ -f "$log" ] || continue
|
||||||
|
[[ "$log" =~ (bytes_log|offset|error_log|ftpxferlog|-ssl_log)$ ]] && continue
|
||||||
|
|
||||||
|
domain="${log##*/}"
|
||||||
|
domain="${domain%%-*}"
|
||||||
|
|
||||||
|
# Find cPanel user for this domain
|
||||||
|
user=$(grep -l "DNS.*$domain" /var/cpanel/users/* 2>/dev/null | head -1 | xargs basename 2>/dev/null)
|
||||||
|
[ -z "$user" ] && user="unknown"
|
||||||
|
|
||||||
|
domain_user["$domain"]="$user"
|
||||||
|
|
||||||
|
# Scan for 500 errors in this log
|
||||||
|
while IFS= read -r line; do
|
||||||
|
# Check for 500 status code
|
||||||
|
if [[ "$line" =~ '"'[[:space:]](5[0-9]{2})[[:space:]] ]]; then
|
||||||
|
status="${BASH_REMATCH[1]}"
|
||||||
|
|
||||||
|
# Time filtering
|
||||||
|
if [ "$cutoff_time" != "0" ]; then
|
||||||
|
if [[ "$line" =~ \[([0-9]{2}/[A-Z][a-z]{2}/[0-9]{4}:[0-9]{2}:[0-9]{2}:[0-9]{2}) ]]; then
|
||||||
|
log_date="${BASH_REMATCH[1]}"
|
||||||
|
log_time=$(date -d "${log_date/:/ }" +%s 2>/dev/null || echo "0")
|
||||||
|
[ "$log_time" != "0" ] && [ "$log_time" -lt "$cutoff_time" ] && continue
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Parse log line
|
||||||
|
read -r ip _ _ timestamp _ request _ _ <<< "$line"
|
||||||
|
|
||||||
|
# Extract URL
|
||||||
|
if [[ "$request" =~ '"'[A-Z]+[[:space:]]([^[:space:]]+) ]]; then
|
||||||
|
url="${BASH_REMATCH[1]:0:80}"
|
||||||
|
else
|
||||||
|
url="/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extract timestamp
|
||||||
|
if [[ "$line" =~ \[([^]]+)\] ]]; then
|
||||||
|
timestamp="${BASH_REMATCH[1]}"
|
||||||
|
else
|
||||||
|
timestamp="unknown"
|
||||||
|
fi
|
||||||
|
|
||||||
|
((domain_count["$domain"]++))
|
||||||
|
((total_500s++))
|
||||||
|
|
||||||
|
# Save for analysis
|
||||||
|
echo "$domain|$user|$status|$url|$timestamp|$ip" >> "$ERRORS_500"
|
||||||
|
fi
|
||||||
|
done < <(tail -n 100000 "$log" 2>/dev/null)
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$total_500s" -eq 0 ]; then
|
||||||
|
echo ""
|
||||||
|
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||||
|
echo -e "${GREEN} ✓ NO 500 ERRORS FOUND IN LAST $HOURS_TO_SCAN HOURS!${NC}"
|
||||||
|
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||||
|
echo ""
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
echo " 🔥 500 ERRORS DETECTED: $total_500s errors"
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo -e "${RED}${BOLD}TOP AFFECTED DOMAINS:${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Sort and display top domains
|
||||||
|
for domain in "${!domain_count[@]}"; do
|
||||||
|
echo "${domain_count[$domain]} $domain ${domain_user[$domain]}"
|
||||||
|
done | sort -rn | head -10 | while read count domain user; do
|
||||||
|
printf " ${RED}●${NC} %-40s ${BOLD}%4d errors${NC} (user: %s)\n" "$domain" "$count" "$user"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
echo " 🔍 DIAGNOSING ROOT CAUSES"
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# For each affected domain, check the actual PHP error logs
|
||||||
|
declare -A diagnosed_causes
|
||||||
|
declare -A cause_examples
|
||||||
|
|
||||||
|
while IFS='|' read -r domain user status url timestamp ip; do
|
||||||
|
[ -z "$domain" ] && continue
|
||||||
|
|
||||||
|
# Find PHP error log for this user
|
||||||
|
error_log="/home/$user/public_html/error_log"
|
||||||
|
|
||||||
|
# Check if error log exists and has recent errors
|
||||||
|
if [ -f "$error_log" ]; then
|
||||||
|
# Look for errors around the same time as the 500
|
||||||
|
recent_error=$(tail -100 "$error_log" | grep -E "Fatal error|Parse error|syntax error|memory.*exhausted|database|MySQL" | tail -1)
|
||||||
|
|
||||||
|
if [ -n "$recent_error" ]; then
|
||||||
|
# Determine cause
|
||||||
|
cause="UNKNOWN"
|
||||||
|
if [[ "$recent_error" =~ (memory.*exhausted|Allowed memory size) ]]; then
|
||||||
|
cause="PHP_MEMORY_EXHAUSTED"
|
||||||
|
cause_examples["$cause"]="$domain: $recent_error"
|
||||||
|
elif [[ "$recent_error" =~ (Fatal error|PHP Fatal error) ]]; then
|
||||||
|
if [[ "$recent_error" =~ (undefined function|Call to undefined function) ]]; then
|
||||||
|
cause="MISSING_PHP_FUNCTION"
|
||||||
|
cause_examples["$cause"]="$domain: $recent_error"
|
||||||
|
else
|
||||||
|
cause="PHP_FATAL_ERROR"
|
||||||
|
cause_examples["$cause"]="$domain: $recent_error"
|
||||||
|
fi
|
||||||
|
elif [[ "$recent_error" =~ (Parse error|syntax error) ]]; then
|
||||||
|
cause="PHP_SYNTAX_ERROR"
|
||||||
|
cause_examples["$cause"]="$domain: $recent_error"
|
||||||
|
elif [[ "$recent_error" =~ (database|MySQL|Can\'t connect) ]]; then
|
||||||
|
cause="DATABASE_CONNECTION"
|
||||||
|
cause_examples["$cause"]="$domain: $recent_error"
|
||||||
|
fi
|
||||||
|
|
||||||
|
((diagnosed_causes["$cause"]++))
|
||||||
|
else
|
||||||
|
((diagnosed_causes["NO_PHP_ERROR_LOGGED"]++))
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
((diagnosed_causes["NO_ERROR_LOG_FILE"]++))
|
||||||
|
cause_examples["NO_ERROR_LOG_FILE"]="$domain (user: $user) - error_log file missing at $error_log"
|
||||||
|
fi
|
||||||
|
done < "$ERRORS_500"
|
||||||
|
|
||||||
|
# Display diagnosed causes
|
||||||
|
echo -e "${CYAN}${BOLD}ROOT CAUSES IDENTIFIED:${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
for cause in "${!diagnosed_causes[@]}"; do
|
||||||
|
count="${diagnosed_causes[$cause]}"
|
||||||
|
echo "$count|$cause"
|
||||||
|
done | sort -rn | while IFS='|' read count cause; do
|
||||||
|
clean_cause=$(echo "$cause" | tr '_' ' ')
|
||||||
|
|
||||||
|
case "$cause" in
|
||||||
|
PHP_MEMORY_EXHAUSTED)
|
||||||
|
echo -e "${RED}🔥 $clean_cause${NC} - $count occurrences"
|
||||||
|
echo " ${YELLOW}Fix:${NC} Increase memory_limit in /home/USER/public_html/.user.ini"
|
||||||
|
echo " ${YELLOW}Set:${NC} memory_limit = 512M"
|
||||||
|
;;
|
||||||
|
PHP_FATAL_ERROR)
|
||||||
|
echo -e "${RED}⚠️ $clean_cause${NC} - $count occurrences"
|
||||||
|
echo " ${YELLOW}Fix:${NC} Review recent code/plugin changes"
|
||||||
|
;;
|
||||||
|
PHP_SYNTAX_ERROR)
|
||||||
|
echo -e "${RED}📝 $clean_cause${NC} - $count occurrences"
|
||||||
|
echo " ${YELLOW}Fix:${NC} Check for PHP syntax errors in recent file edits"
|
||||||
|
;;
|
||||||
|
MISSING_PHP_FUNCTION)
|
||||||
|
echo -e "${RED}📦 $clean_cause${NC} - $count occurrences"
|
||||||
|
echo " ${YELLOW}Fix:${NC} Install missing PHP extension (check error for which one)"
|
||||||
|
;;
|
||||||
|
DATABASE_CONNECTION)
|
||||||
|
echo -e "${RED}🗄️ $clean_cause${NC} - $count occurrences"
|
||||||
|
echo " ${YELLOW}Fix:${NC} Check database credentials or MySQL service"
|
||||||
|
;;
|
||||||
|
NO_ERROR_LOG_FILE)
|
||||||
|
echo -e "${YELLOW}📄 $clean_cause${NC} - $count occurrences"
|
||||||
|
echo " ${YELLOW}Note:${NC} error_log file doesn't exist - may be .htaccess or permission issue"
|
||||||
|
;;
|
||||||
|
NO_PHP_ERROR_LOGGED)
|
||||||
|
echo -e "${YELLOW}❓ $clean_cause${NC} - $count occurrences"
|
||||||
|
echo " ${YELLOW}Note:${NC} 500 error but no PHP error in log - likely .htaccess issue"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo -e "${INFO_COLOR}• $clean_cause${NC} - $count occurrences"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Show example if we have one
|
||||||
|
if [ -n "${cause_examples[$cause]}" ]; then
|
||||||
|
example="${cause_examples[$cause]}"
|
||||||
|
echo " ${DIM}Example: ${example:0:120}...${NC}"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
echo " 📋 DETAILED 500 ERROR LIST"
|
||||||
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Show most frequent URLs getting 500s
|
||||||
|
echo "Most Frequent 500 Error URLs:"
|
||||||
|
echo ""
|
||||||
|
cut -d'|' -f1,4 "$ERRORS_500" | sort | uniq -c | sort -rn | head -15 | while read count domain_url; do
|
||||||
|
domain=$(echo "$domain_url" | cut -d'|' -f1)
|
||||||
|
url=$(echo "$domain_url" | cut -d'|' -f2)
|
||||||
|
user="${domain_user[$domain]}"
|
||||||
|
printf " ${RED}%4d×${NC} %s%s ${DIM}(user: %s)${NC}\n" "$count" "$domain" "$url" "$user"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Full error list saved to: $ERRORS_500"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
press_enter
|
||||||
@@ -604,10 +604,10 @@ END {
|
|||||||
file_path = file[key]
|
file_path = file[key]
|
||||||
|
|
||||||
# Skip empty errors
|
# Skip empty errors
|
||||||
if (length(error) == 0) next
|
if (length(error) > 0) {
|
||||||
|
|
||||||
print count[key] "|" domain "|" file_path "|" error "|" root_cause
|
print count[key] "|" domain "|" file_path "|" error "|" root_cause
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}' "$CRITICAL_ERRORS" | sort -t'|' -k1 -rn | head -20 | while IFS='|' read -r count domain file_path error_msg root_cause; do
|
}' "$CRITICAL_ERRORS" | sort -t'|' -k1 -rn | head -20 | while IFS='|' read -r count domain file_path error_msg root_cause; do
|
||||||
|
|
||||||
# Color code by frequency
|
# Color code by frequency
|
||||||
|
|||||||
Reference in New Issue
Block a user