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
teeoutputs 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"
fiLearn 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 listFunction 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_pluginsVariable 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_COUNTLearn 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 --allStack 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 -deleteUsing 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" 5Log 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"
fiCentralized 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.
Recommended Learning Path
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
- Distributed Tracing – Track operations across systems
- Log Analytics – Advanced log parsing and insights
- Monitoring Dashboards – Visualize log data
Get More Resources
Download logging templates including:
- Complete logging systems
- Analysis scripts
- Monitoring tools
- 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.
