Professional Logging and Debugging for WP-CLI Automation Scripts

Your WordPress automation script fails at 3 AM, but you have no idea what went wrong—no logs, no error messages, no trace of what happened. Debugging production scripts without proper logging means guessing, recreating issues, and wasting hours troubleshooting.

Professional logging transforms opaque scripts into transparent, debuggable systems. Track every operation, capture errors with context, monitor script health, and diagnose failures instantly with comprehensive logs that tell the complete story.

In this guide, you’ll learn professional logging and debugging techniques for WP-CLI automation scripts, from basic logging to advanced monitoring systems used by DevOps teams managing critical WordPress infrastructure.

Why Logging Matters for Automation Scripts

Bash scripting without logging is like driving blindfolded—you don’t know what’s happening until something crashes.

Problems Without Proper Logging

Silent failures: Scripts fail without leaving any trace of what went wrong.

No audit trail: Can’t verify what scripts did or when they ran.

Difficult debugging: Recreating issues requires guessing and trial-and-error.

No monitoring: Can’t track script health or detect degrading performance.

Compliance issues: Can’t prove what operations were performed when.

Professional Logging Benefits

Instant diagnosis: Know exactly what failed and why from log messages.

Complete audit trail: Track every operation for compliance and debugging.

Proactive monitoring: Detect issues before they become critical failures.

Performance tracking: Identify bottlenecks and optimization opportunities.

Team collaboration: Share logs for troubleshooting across teams.

According to DevOps best practices, comprehensive logging reduces mean time to recovery (MTTR) by 80%.

Basic Logging Implementation

Start with fundamental logging patterns for WP-CLI scripts.

Simple Log Function

#!/bin/bash
# basic-logging.sh

LOG_FILE="/var/log/wp-automation.log"

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $@" | tee -a "$LOG_FILE"
}

# Usage
log "Script started"
log "Updating WordPress plugins..."

wp plugin update --all

if [ $? -eq 0 ]; then
    log "✓ Plugins updated successfully"
else
    log "✗ Plugin update failed"
fi

log "Script completed"

Key Elements:

  • Timestamp for every log entry
  • tee outputs to both terminal and file
  • Exit codes checked and logged

Logging Command Output

#!/bin/bash

LOG_FILE="/var/log/wp-updates.log"

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $@" | tee -a "$LOG_FILE"
}

log "Starting WordPress update"

# Capture command output and log it
OUTPUT=$(wp core update 2>&1)
EXIT_CODE=$?

echo "$OUTPUT" >> "$LOG_FILE"

if [ $EXIT_CODE -eq 0 ]; then
    log "✓ WordPress updated successfully"
else
    log "✗ WordPress update failed with exit code $EXIT_CODE"
    log "Output: $OUTPUT"
fi

Learn about Bash redirection for capturing output.

Log Levels and Structured Logging

Implement professional log levels for better organization.

Multi-Level Logging System

#!/bin/bash
# logging-levels.sh

LOG_FILE="/var/log/wp-automation.log"
LOG_LEVEL="${LOG_LEVEL:-INFO}"  # Default to INFO

# Log level hierarchy: DEBUG < INFO < WARN < ERROR
declare -A LOG_LEVELS=([DEBUG]=0 [INFO]=1 [WARN]=2 [ERROR]=3)

log() {
    local level="$1"
    shift
    local message="$@"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')

    # Check if we should log this level
    if [ "${LOG_LEVELS[$level]}" -ge "${LOG_LEVELS[$LOG_LEVEL]}" ]; then
        echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
    fi
}

log_debug() { log DEBUG "$@"; }
log_info() { log INFO "$@"; }
log_warn() { log WARN "$@"; }
log_error() { log ERROR "$@"; }

# Usage examples
log_debug "Starting database backup process"
log_info "Backing up WordPress database"
log_warn "Database size exceeds 1GB, this may take a while"
log_error "Database backup failed: disk full"

Structured Log Format

#!/bin/bash
# structured-logging.sh

log_structured() {
    local level="$1"
    local component="$2"
    local action="$3"
    shift 3
    local message="$@"

    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    local hostname=$(hostname)

    # JSON-like format for easy parsing
    echo "{\"timestamp\":\"$timestamp\",\"level\":\"$level\",\"host\":\"$hostname\",\"component\":\"$component\",\"action\":\"$action\",\"message\":\"$message\"}" >> "$LOG_FILE"

    # Human-readable format for terminal
    echo "[$timestamp] [$level] [$component] $action: $message"
}

# Usage
log_structured INFO "wordpress" "plugin-update" "Updating all plugins"
log_structured ERROR "database" "backup" "Failed to create backup: Permission denied"

Debugging Techniques

Advanced debugging patterns for troubleshooting scripts.

Bash Debug Mode

#!/bin/bash

# Enable debug mode with -x flag
set -x  # Print each command before executing

# Or use for specific sections
{
    set -x
    wp plugin update --all
    wp theme update --all
    set +x
} 2>&1 | tee -a debug.log

# Verbose WP-CLI output
wp --debug plugin list

Function Tracing

#!/bin/bash

# Enable function call tracing
set -o functrace

# Trace function for debugging
trace() {
    echo "[TRACE] Function: ${FUNCNAME[1]}, Line: ${BASH_LINENO[0]}" >> trace.log
}

backup_database() {
    trace
    log_info "Starting database backup"
    wp db export backup.sql.gz
}

update_plugins() {
    trace
    log_info "Updating plugins"
    wp plugin update --all
}

# Call functions
backup_database
update_plugins

Variable State Logging

#!/bin/bash

log_var() {
    local var_name="$1"
    local var_value="${!var_name}"
    log_debug "Variable $var_name = '$var_value'"
}

# Usage
BACKUP_DIR="/backups"
SITE_URL="https://example.com"
PLUGIN_COUNT=$(wp plugin list --format=count)

log_var BACKUP_DIR
log_var SITE_URL
log_var PLUGIN_COUNT

Learn about Bash debugging techniques.

Error Context and Stack Traces

Capture comprehensive error information for debugging.

Error Handler with Context

#!/bin/bash
set -euo pipefail

LOG_FILE="/var/log/wp-errors.log"

error_handler() {
    local exit_code=$?
    local line_number=$1
    local bash_lineno=${BASH_LINENO[0]}
    local function_name=${FUNCNAME[1]:-main}
    local command="${BASH_COMMAND}"

    {
        echo "=========================================="
        echo "ERROR OCCURRED"
        echo "=========================================="
        echo "Timestamp: $(date '+%Y-%m-%d %H:%M:%S')"
        echo "Exit Code: $exit_code"
        echo "Line Number: $line_number"
        echo "Function: $function_name"
        echo "Command: $command"
        echo "Script: $0"
        echo "Working Directory: $(pwd)"
        echo "User: $(whoami)"
        echo "Hostname: $(hostname)"
        echo "=========================================="
    } | tee -a "$LOG_FILE"

    # Capture environment state
    echo "Environment Variables:" >> "$LOG_FILE"
    env >> "$LOG_FILE"

    exit $exit_code
}

trap 'error_handler ${LINENO}' ERR

# Script operations that might fail
wp db export backup.sql.gz
wp plugin update --all

Stack Trace Function

#!/bin/bash

print_stack_trace() {
    local frame=0
    echo "Stack Trace:" >&2

    while caller $frame; do
        ((frame++))
    done | while read line func file; do
        echo "  at $func ($file:$line)" >&2
    done
}

error_with_trace() {
    echo "ERROR: $@" >&2
    print_stack_trace
}

# Usage
backup_db() {
    if ! wp db export backup.sql.gz; then
        error_with_trace "Database backup failed"
        return 1
    fi
}

Log Rotation and Management

Prevent logs from consuming all disk space.

Manual Log Rotation

#!/bin/bash
# rotate-logs.sh - Rotate log files

LOG_FILE="/var/log/wp-automation.log"
MAX_SIZE_MB=10
KEEP_DAYS=30

# Check log file size
if [ -f "$LOG_FILE" ]; then
    FILE_SIZE=$(du -m "$LOG_FILE" | cut -f1)

    if [ "$FILE_SIZE" -gt "$MAX_SIZE_MB" ]; then
        echo "Rotating log file (${FILE_SIZE}MB)"

        # Archive with timestamp
        ARCHIVE="${LOG_FILE}.$(date +%Y%m%d-%H%M%S).gz"
        gzip -c "$LOG_FILE" > "$ARCHIVE"

        # Clear current log
        > "$LOG_FILE"

        echo "Log rotated to: $ARCHIVE"
    fi
fi

# Delete old archives
find "$(dirname $LOG_FILE)" -name "$(basename $LOG_FILE).*.gz" -mtime +$KEEP_DAYS -delete

Using logrotate

# /etc/logrotate.d/wp-automation

/var/log/wp-automation.log {
    daily
    rotate 7
    compress
    delaycompress
    missingok
    notifempty
    create 0640 www-data www-data
    sharedscripts
    postrotate
        # Optional: restart service if needed
    endscript
}

Learn about logrotate configuration.

Performance and Timing Logs

Track script performance and identify bottlenecks.

Execution Time Logging

#!/bin/bash

log_timed() {
    local description="$1"
    shift
    local command="$@"

    log_info "Starting: $description"
    local start_time=$(date +%s)

    # Execute command
    eval "$command"
    local exit_code=$?

    local end_time=$(date +%s)
    local duration=$((end_time - start_time))

    if [ $exit_code -eq 0 ]; then
        log_info "✓ Completed: $description (${duration}s)"
    else
        log_error "✗ Failed: $description (${duration}s, exit code: $exit_code)"
    fi

    return $exit_code
}

# Usage
log_timed "Database export" "wp db export backup.sql.gz"
log_timed "Plugin updates" "wp plugin update --all"
log_timed "Cache flush" "wp cache flush"

Performance Benchmarking

#!/bin/bash

benchmark() {
    local operation="$1"
    local iterations="${2:-10}"

    log_info "Benchmarking: $operation ($iterations iterations)"

    local total_time=0

    for i in $(seq 1 $iterations); do
        local start=$(date +%s%N)
        eval "$operation" >/dev/null 2>&1
        local end=$(date +%s%N)

        local duration=$(( (end - start) / 1000000 ))  # Convert to milliseconds
        total_time=$((total_time + duration))
    done

    local avg_time=$((total_time / iterations))

    log_info "Benchmark results: ${avg_time}ms average (${iterations} runs)"
}

# Usage
benchmark "wp option get siteurl" 5

Log Aggregation and Analysis

Analyze logs for insights and troubleshooting.

Log Analysis Scripts

#!/bin/bash
# analyze-logs.sh - Extract insights from logs

LOG_FILE="/var/log/wp-automation.log"

echo "WordPress Automation Log Analysis"
echo "=================================="
echo ""

# Count log levels
echo "Log Levels:"
echo "  ERROR:   $(grep -c '\[ERROR\]' "$LOG_FILE")"
echo "  WARN:    $(grep -c '\[WARN\]' "$LOG_FILE")"
echo "  INFO:    $(grep -c '\[INFO\]' "$LOG_FILE")"
echo ""

# Recent errors
echo "Recent Errors (last 10):"
grep '\[ERROR\]' "$LOG_FILE" | tail -10
echo ""

# Most common operations
echo "Most Frequent Operations:"
grep -oP '(?<=\] ).*?(?=:)' "$LOG_FILE" | sort | uniq -c | sort -rn | head -10
echo ""

# Script execution times
echo "Average Execution Times:"
grep -oP 'Completed.*?\(\K[0-9]+(?=s\))' "$LOG_FILE" | awk '{sum+=$1; count++} END {print "Average: " sum/count "s"}'

Error Report Generation

#!/bin/bash
# generate-error-report.sh

LOG_FILE="/var/log/wp-automation.log"
REPORT_FILE="/tmp/error-report-$(date +%Y%m%d).txt"
EMAIL="admin@example.com"

{
    echo "WordPress Automation Error Report"
    echo "Generated: $(date)"
    echo "=================================="
    echo ""

    # Errors in last 24 hours
    echo "Errors in Last 24 Hours:"
    grep '\[ERROR\]' "$LOG_FILE" | grep "$(date +%Y-%m-%d)" | nl
    echo ""

    # Failed operations
    echo "Failed Operations:"
    grep '✗ Failed' "$LOG_FILE" | tail -20
    echo ""

    # Critical errors
    echo "Critical Issues:"
    grep -i 'critical\|fatal\|emergency' "$LOG_FILE" | tail -10

} > "$REPORT_FILE"

# Email report if errors found
ERROR_COUNT=$(grep -c '\[ERROR\]' "$LOG_FILE" || true)
if [ "$ERROR_COUNT" -gt 0 ]; then
    mail -s "WordPress Automation Errors: $ERROR_COUNT found" "$EMAIL" < "$REPORT_FILE"
fi

Centralized Logging Systems

Send logs to centralized logging platforms.

Syslog Integration

#!/bin/bash

# Log to both file and syslog
log_to_syslog() {
    local level="$1"
    shift
    local message="$@"

    # Map to syslog levels
    case "$level" in
        ERROR) priority="err" ;;
        WARN)  priority="warning" ;;
        INFO)  priority="info" ;;
        DEBUG) priority="debug" ;;
        *) priority="notice" ;;
    esac

    # Log to file
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$level] $message" >> "$LOG_FILE"

    # Log to syslog
    logger -t "wp-automation" -p "user.${priority}" "$message"
}

# Usage
log_to_syslog INFO "Starting WordPress backup"
log_to_syslog ERROR "Backup failed: disk full"

JSON Logging for Parsing

#!/bin/bash

log_json() {
    local level="$1"
    shift
    local message="$@"

    local json=$(cat <<EOF
{
  "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "level": "$level",
  "service": "wp-automation",
  "hostname": "$(hostname)",
  "message": "$message",
  "script": "$0",
  "pid": $
}
EOF
)

    echo "$json" >> /var/log/wp-automation.json
}

# Usage
log_json "info" "WordPress backup started"
log_json "error" "Plugin update failed"

Next Steps

You now have professional logging and debugging skills for production-ready WP-CLI automation.

Week 1: Basic logging

  • Implement log functions
  • Add timestamps and levels
  • Practice log file rotation

Week 2: Advanced debugging

  • Use debug modes
  • Add error handlers
  • Capture stack traces

Week 3: Performance tracking

  • Log execution times
  • Benchmark operations
  • Identify bottlenecks

Week 4: Production monitoring

  • Set up log analysis
  • Configure alerting
  • Implement centralized logging

Advanced Topics

  1. Distributed Tracing – Track operations across systems
  2. Log Analytics – Advanced log parsing and insights
  3. Monitoring Dashboards – Visualize log data

Get More Resources

Download logging templates including:

  • Complete logging systems
  • Analysis scripts
  • Monitoring tools

Join our email course for:

  • Weekly WP-CLI tutorials
  • Debugging best practices
  • DevOps logging strategies

Conclusion

Professional logging and debugging transform fragile WordPress automation scripts into transparent, maintainable systems that provide complete visibility into operations.

What we covered:

✅ Basic logging implementation with timestamps ✅ Multi-level logging systems (DEBUG, INFO, WARN, ERROR) ✅ Advanced debugging techniques and tracing ✅ Error context and stack trace capture ✅ Log rotation and management ✅ Performance tracking and analysis

Master these techniques, and you’ll never struggle to debug production scripts again—comprehensive logs tell you exactly what happened, when, and why.

Ready for more? Learn monitoring and alerting or production debugging workflows.

Questions about logging WP-CLI automation scripts? Drop a comment below!

Found this helpful? Share with other DevOps engineers.