Skip to content

Instantly share code, notes, and snippets.

@davemac
Last active July 28, 2025 01:44
Show Gist options
  • Select an option

  • Save davemac/e9d000e82f4d130ffa400a1efa75f59f to your computer and use it in GitHub Desktop.

Select an option

Save davemac/e9d000e82f4d130ffa400a1efa75f59f to your computer and use it in GitHub Desktop.

Revisions

  1. davemac revised this gist Jul 28, 2025. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -1,8 +1,8 @@
    #!/bin/zsh

    # WordPress Plugin Memory Isolation Testing Script
    # WordPress Plugin Fatal Error Diagnostic Script
    #
    # Purpose: Systematically test individual plugins to isolate memory exhaustion issues
    # 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)
    #
  2. davemac revised this gist Jul 28, 2025. No changes.
  3. davemac revised this gist Jul 28, 2025. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -3,6 +3,7 @@
    # WordPress Plugin Memory Isolation Testing Script
    #
    # Purpose: Systematically test individual plugins to isolate memory exhaustion issues
    # Setup: chmod +x plugin-memory.sh (make executable - only needed once)
    # Usage: ./plugin-memory.sh (run from WordPress root directory)
    #
    # What it does:
  4. davemac created this gist Jul 28, 2025.
    263 changes: 263 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,263 @@
    #!/bin/zsh

    # WordPress Plugin Memory Isolation Testing Script
    #
    # Purpose: Systematically test individual plugins to isolate memory exhaustion issues
    # 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"