#!/bin/zsh # WordPress Plugin Fatal Error Diagnostic Script # # Purpose: Systematically test individual plugins to isolate fatal error issues # Setup: chmod +x plugin-memory.sh (make executable - only needed once) # Usage: ./plugin-memory.sh (run from WordPress root directory) # # What it does: # 1. Auto-detects site URL using wp-cli (wp option get home) # 2. Auto-detects all currently active plugins using wp-cli # 3. Tests each plugin individually by deactivating it # 4. Clears debug log and makes a site request # 5. Checks for fatal memory errors in wp-content/debug.log # 6. Reactivates the plugin and moves to the next one # 7. Saves detailed output to timestamped log file # # Key Features: # - Fully automatic detection (site URL + active plugins) # - Configurable skip list for critical plugins # - macOS/zsh compatible (uses zsh array syntax) # - Interactive mode - stops when culprit is found # - Logging to both terminal and file # # Output: plugin_memory_test_YYYYMMDD_HHMMSS.txt with full test results set -e # Exit on any error # Create output file with timestamp OUTPUT_FILE="plugin_memory_test_$(date +%Y%m%d_%H%M%S).txt" # Function to output to both terminal and file output() { echo "$@" | tee -a "$OUTPUT_FILE" } # Configuration LOG_FILE="wp-content/debug.log" # Colours for output (only for terminal) RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Colour # Plugins to skip (add plugin names here that should never be tested) # Example: critical security plugins, backup plugins, etc. SKIP_PLUGINS="wordfence akismet updraftplus" # Function to print coloured output print_status() { local colour=$1 local message=$2 echo -e "${colour}${message}${NC}" | tee -a "$OUTPUT_FILE" } # Initialize output file echo "WordPress Plugin Memory Error Testing Script Output" > "$OUTPUT_FILE" echo "Generated: $(date)" >> "$OUTPUT_FILE" echo "========================================" >> "$OUTPUT_FILE" # Check if we're in a WordPress directory if [[ ! -f "wp-config.php" ]]; then print_status $RED "Error: This script must be run from the WordPress root directory" exit 1 fi print_status $YELLOW "Starting WordPress plugin memory error testing..." output "Output will be saved to: $OUTPUT_FILE" # Check wp-cli availability first if ! command -v wp &> /dev/null; then print_status $RED "Error: wp-cli is not installed or not in PATH" print_status $YELLOW "Please install wp-cli: https://wp-cli.org/" exit 1 fi # Auto-detect site URL using wp-cli output "Detecting site URL..." SITE_URL=$(wp option get home 2>/dev/null) if [[ -z "$SITE_URL" ]]; then print_status $RED "Error: Could not retrieve site URL" print_status $YELLOW "Make sure wp-cli is working: wp option get home" exit 1 fi print_status $YELLOW "Site URL: $SITE_URL" print_status $YELLOW "Log file: $LOG_FILE" output "" # Auto-detect active plugins using wp-cli output "Detecting active plugins..." # Get list of active plugins PLUGINS=$(wp plugin list --status=active --field=name 2>/dev/null) if [[ -z "$PLUGINS" ]]; then print_status $RED "Error: Could not retrieve active plugins list" print_status $YELLOW "Make sure wp-cli is working: wp plugin list" exit 1 fi # Convert to array and filter out skipped plugins plugins_array=() skip_array=(${=SKIP_PLUGINS}) # Convert newline-separated plugin list to array while IFS= read -r plugin; do [[ -n "$plugin" ]] || continue # Skip empty lines # Check if plugin should be skipped skip_plugin=false for skip in "${skip_array[@]}"; do if [[ "$plugin" == "$skip" ]]; then output "⏭️ Skipping plugin: $plugin (in skip list)" skip_plugin=true break fi done if [[ "$skip_plugin" == false ]]; then plugins_array+=("$plugin") fi done <<< "$PLUGINS" # Display detected plugins output "Found ${#plugins_array[@]} active plugins to test:" for plugin in "${plugins_array[@]}"; do output " - $plugin" done output "" # Explain what we're looking for print_status $YELLOW "🔍 What this script detects:" output " • Fatal memory errors: 'Allowed memory size of X bytes exhausted'" output " • PHP fatal errors: 'PHP Fatal error' messages" output " • Memory-related crashes that prevent site loading" output "" output "✅ Success criteria: Site loads without fatal errors when plugin is deactivated" output "❌ Problem identified: Fatal errors disappear when specific plugin is deactivated" output "" # Pre-check: Verify there's actually a fatal error to solve print_status $YELLOW "🔬 Pre-check: Testing site with all plugins active..." output "Clearing debug log..." rm "$LOG_FILE" 2>/dev/null && touch "$LOG_FILE" output "Making test request to site..." if curl -s --max-time 10 --connect-timeout 5 --insecure "$SITE_URL" > /dev/null 2>&1; then output "Site request successful" # Wait for logs to be written sleep 1 # Check for fatal errors if ! grep -q "Fatal error" "$LOG_FILE" 2>/dev/null; then print_status $GREEN "✅ No fatal errors found!" output "" output "The site is currently working fine with all plugins active." output "This script is designed to isolate plugins causing fatal errors." output "" print_status $YELLOW "Possible reasons:" output " • The issue has already been resolved" output " • The error only occurs under specific conditions" output " • The error is intermittent" output " • The error is theme-related, not plugin-related" output "" output "If you're still experiencing issues, try:" output " • Access different pages of your site" output " • Check wp-content/debug.log manually" output " • Use other diagnostic scripts in this directory" output "" output "Full output saved to: $OUTPUT_FILE" exit 0 else print_status $RED "❌ Fatal errors detected!" output "Error details:" grep "Fatal error" "$LOG_FILE" 2>/dev/null | head -3 | while read -r error_line; do output " $error_line" done output "" print_status $YELLOW "Proceeding with plugin isolation testing..." output "" fi else print_status $RED "⚠️ Could not reach site - proceeding with testing anyway" output "This might indicate a severe error that prevents site loading" output "" fi for plugin in "${plugins_array[@]}"; do output "Testing plugin: $plugin" # Deactivate plugin (removed timeout - this was causing the hangs) output " → Deactivating plugin..." if wp plugin deactivate "$plugin" --quiet 2>/dev/null; then output " → Plugin deactivated successfully" # Clear log file (using method that works on macOS) output " → Clearing log file..." rm "$LOG_FILE" 2>/dev/null && touch "$LOG_FILE" output " → Log file cleared successfully" # Wait a moment for any pending operations output " → Waiting 2 seconds for changes to take effect..." sleep 2 output " → Wait complete" # Make request to site output " → Making request to site ($SITE_URL)..." output " → Running: curl -s --max-time 10 --connect-timeout 5 --insecure $SITE_URL" if curl -s --max-time 10 --connect-timeout 5 --insecure "$SITE_URL" > /dev/null 2>&1; then output " → Site request successful" # Wait a moment for logs to be written sleep 1 # Check for fatal errors in log output " → Checking log file for fatal errors..." output " → Searching for pattern: 'Fatal error' in $LOG_FILE" if ! grep -q "Fatal error" "$LOG_FILE" 2>/dev/null; then print_status $GREEN "✅ Fatal error GONE when $plugin is deactivated. This is the culprit!" # Ask if user wants to stop here print_status $YELLOW "Found the problematic plugin: $plugin" echo "Would you like to stop testing here? (y/n): " read -r response output "User response: $response" if [[ "$response" =~ ^[Yy]$ ]]; then print_status $YELLOW "Testing stopped at user request" output "Plugin causing issues: $plugin" # Reactivate the plugin before exiting output "Reactivating problematic plugin..." wp plugin activate "$plugin" --quiet 2>/dev/null output "Full output saved to: $OUTPUT_FILE" exit 0 fi else print_status $RED "❌ Fatal error still present with $plugin deactivated" output " → Error details:" grep "Fatal error" "$LOG_FILE" 2>/dev/null | head -2 | while read -r error_line; do output " $error_line" done fi else print_status $YELLOW "⚠️ Could not reach site or request failed" fi # Reactivate plugin (removed timeout) output " → Reactivating plugin..." if wp plugin activate "$plugin" --quiet 2>/dev/null; then output " → Plugin reactivated successfully" else print_status $RED "Warning: Could not reactivate plugin '$plugin'" fi else print_status $RED "Error: Could not deactivate plugin '$plugin'" fi output "---------------------------------" done print_status $YELLOW "Testing complete!" output "Full output saved to: $OUTPUT_FILE"