Your WordPress automation script runs perfectly 99% of the time. Then one day it silently fails during a database import, deletes files you meant to keep, or corrupts data because a command returned an error you never checked. Production is down.
Bash scripts without proper error handling are disasters waiting to happen. One unchecked exit code, one missing validation, and your automation becomes your biggest liability instead of your greatest asset.
In this guide, youβll learn professional error handling techniques that prevent script failures, protect your data, and make WP-CLI automation scripts production-ready and bulletproof.
Why Error Handling Matters for WP-CLI Scripts
Bash scripting by default continues executing after errors occur, which is dangerous for WordPress operations.
Problems with Poor Error Handling
Silent failures: Scripts continue after failed database exports, creating incomplete backups.
Data corruption: Import scripts run on wrong databases because connection checks were skipped.
Partial operations: Plugin updates fail halfway through, leaving sites in broken states.
No recovery: Scripts canβt rollback or cleanup after failures.
Debugging nightmares: No logs or error messages make troubleshooting impossible.
Professional Error Handling Benefits
Early failure detection: Scripts stop immediately when errors occur.
Safe operations: Validate inputs and check preconditions before making changes.
Automatic cleanup: Trap errors and perform cleanup even during failures.
Detailed logging: Track exactly what failed and why for quick debugging.
Production-ready: Confidence to run scripts on live sites without supervision.
According to DevOps research, organizations with robust error handling in automation scripts experience 60% fewer outages.
Bash Error Handling Fundamentals
Master the core error handling mechanisms in Bash.
Exit Codes and $? Variable
# Every command returns exit code
# 0 = success, non-zero = failure
wp core version
echo $? # Prints 0 if successful
wp plugin install nonexistent-plugin
echo $? # Prints non-zero (1) if failed
# Check exit code immediately
if [ $? -eq 0 ]; then
echo "Success"
else
echo "Failed"
fiBetter: Check Exit Codes Inline
# Check command directly in if statement
if wp core is-installed; then
echo "WordPress is installed"
else
echo "WordPress not found"
exit 1
fi
# Using && for success chaining
wp db export backup.sql && echo "Backup successful"
# Using || for failure handling
wp db export backup.sql || { echo "Backup failed!"; exit 1; }Pro Tip: Always check exit codes for destructive operations like database imports, file deletions, or updates.
Set Error Handling Mode
#!/bin/bash
# Exit on any error
set -e
# Exit on undefined variables
set -u
# Pipe failures cause script failure
set -o pipefail
# Combined (recommended)
set -euo pipefail
# Now script exits automatically on errors
wp db export backup.sql # Script exits if this fails
wp plugin update --all # Never runs if above failedLearn more about Bash set options.
Validation and Precondition Checking
Verify assumptions before executing dangerous operations.
Check File Existence
#!/bin/bash
set -euo pipefail
BACKUP_FILE="/backups/database.sql.gz"
# Check file exists before import
if [ ! -f "$BACKUP_FILE" ]; then
echo "Error: Backup file not found: $BACKUP_FILE"
exit 1
fi
# Verify file size (not empty)
FILE_SIZE=$(stat -c%s "$BACKUP_FILE")
if [ "$FILE_SIZE" -lt 1000 ]; then
echo "Error: Backup file too small (${FILE_SIZE} bytes), may be corrupted"
exit 1
fi
# Safe to import
wp db import "$BACKUP_FILE"Validate WordPress Installation
#!/bin/bash
set -euo pipefail
# Check WordPress is installed
if ! wp core is-installed 2>/dev/null; then
echo "Error: WordPress not installed in current directory"
exit 1
fi
# Check database connection
if ! wp db check 2>/dev/null; then
echo "Error: Database connection failed"
exit 1
fi
echo "β WordPress installation validated"Check Required Commands Exist
#!/bin/bash
set -euo pipefail
# Function to check command availability
check_command() {
if ! command -v "$1" &> /dev/null; then
echo "Error: Required command '$1' not found"
echo "Install it with: apt-get install $1"
exit 1
fi
}
# Verify dependencies
check_command wp
check_command mysql
check_command gzip
echo "β All required commands available"Error Trapping and Cleanup
Handle errors gracefully and cleanup resources even during failures.
Basic Trap Command
#!/bin/bash
set -euo pipefail
# Cleanup function
cleanup() {
echo "Cleaning up temporary files..."
rm -f /tmp/temp-backup-*.sql
echo "Cleanup complete"
}
# Register cleanup to run on exit
trap cleanup EXIT
# Script continues normally
echo "Starting backup..."
wp db export /tmp/temp-backup-$(date +%s).sql.gz
# cleanup() runs automatically when script exitsError-Specific Trap
#!/bin/bash
set -euo pipefail
# Error handler
error_handler() {
local exit_code=$?
local line_number=$1
echo "ERROR: Script failed at line $line_number with exit code $exit_code"
echo "Rolling back changes..."
# Perform rollback operations
wp db import /backups/before-update.sql.gz 2>/dev/null || true
exit $exit_code
}
# Trap errors and call error_handler with line number
trap 'error_handler ${LINENO}' ERR
# Backup before changes
wp db export /backups/before-update.sql.gz
# Risky operation
wp plugin update --all
# If above fails, error_handler restores databaseUse Case: Automatically restore database backups if update operations fail mid-process.
Advanced Trap with Multiple Signals
#!/bin/bash
set -euo pipefail
TEMP_DIR="/tmp/wp-deploy-$$"
BACKUP_FILE=""
# Comprehensive cleanup
cleanup() {
local exit_code=$?
if [ $exit_code -ne 0 ]; then
echo "Script failed (exit code: $exit_code)"
echo "Performing emergency cleanup..."
fi
# Remove temporary directory
[ -d "$TEMP_DIR" ] && rm -rf "$TEMP_DIR"
# Remove temporary backup
[ -n "$BACKUP_FILE" ] && rm -f "$BACKUP_FILE"
echo "Cleanup complete"
}
# Trap multiple signals
trap cleanup EXIT ERR INT TERM
# Create temp directory
mkdir -p "$TEMP_DIR"
# Store backup location
BACKUP_FILE="/tmp/backup-$$.sql.gz"
# Script operations...Input Validation and Argument Parsing
Validate script arguments and user inputs before processing.
Validate Required Arguments
#!/bin/bash
set -euo pipefail
# Check argument count
if [ $# -lt 2 ]; then
echo "Usage: $0 <source_url> <target_url>"
echo "Example: $0 https://oldsite.com https://newsite.com"
exit 1
fi
SOURCE_URL="$1"
TARGET_URL="$2"
# Validate URL format
if [[ ! "$SOURCE_URL" =~ ^https?:// ]]; then
echo "Error: Source URL must start with http:// or https://"
exit 1
fi
if [[ ! "$TARGET_URL" =~ ^https?:// ]]; then
echo "Error: Target URL must start with http:// or https://"
exit 1
fi
# Safe to proceed
wp search-replace "$SOURCE_URL" "$TARGET_URL"Validate User Confirmation
#!/bin/bash
set -euo pipefail
echo "WARNING: This will delete all WordPress posts"
echo "This action cannot be undone!"
read -p "Type 'DELETE' to confirm: " CONFIRMATION
if [ "$CONFIRMATION" != "DELETE" ]; then
echo "Operation cancelled"
exit 0
fi
# User confirmed, proceed with deletion
wp post delete $(wp post list --format=ids) --forceValidate Numeric Inputs
#!/bin/bash
set -euo pipefail
DAYS_TO_KEEP="${1:-7}"
# Ensure input is a number
if ! [[ "$DAYS_TO_KEEP" =~ ^[0-9]+$ ]]; then
echo "Error: Days must be a positive number"
exit 1
fi
# Ensure reasonable range
if [ "$DAYS_TO_KEEP" -lt 1 ] || [ "$DAYS_TO_KEEP" -gt 365 ]; then
echo "Error: Days must be between 1 and 365"
exit 1
fi
# Delete old backups
find /backups -name "*.sql.gz" -mtime +$DAYS_TO_KEEP -deleteLogging and Error Reporting
Track script execution and failures with comprehensive logging.
Basic Logging Function
#!/bin/bash
set -euo pipefail
LOG_FILE="/var/log/wp-automation.log"
# Logging function
log() {
local level="$1"
shift
local message="$@"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
}
# Usage
log INFO "Starting WordPress backup"
log WARNING "Database size is large, this may take a while"
log ERROR "Backup failed: disk full"Log with Script Context
#!/bin/bash
set -euo pipefail
LOG_FILE="/var/log/wp-scripts.log"
SCRIPT_NAME=$(basename "$0")
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$SCRIPT_NAME] $@" | tee -a "$LOG_FILE"
}
log "Script started"
log "Backing up database..."
if wp db export backup.sql.gz; then
log "β Database backup successful"
else
log "β Database backup failed"
exit 1
fi
log "Script completed"Email Notifications on Failure
#!/bin/bash
set -euo pipefail
ADMIN_EMAIL="admin@example.com"
# Error handler with email notification
error_notify() {
local exit_code=$?
local line_number=$1
# Prepare error message
ERROR_MSG="WordPress automation script failed
Script: $0
Line: $line_number
Exit Code: $exit_code
Time: $(date)
Server: $(hostname)
Please investigate immediately."
# Log error
echo "$ERROR_MSG" >> /var/log/wp-errors.log
# Send email
echo "$ERROR_MSG" | mail -s "ALERT: WordPress Script Failure" "$ADMIN_EMAIL"
exit $exit_code
}
trap 'error_notify ${LINENO}' ERR
# Script operations...Production-Ready Error Handling Patterns
Complete error handling templates for common WP-CLI operations.
Safe Database Migration Script
#!/bin/bash
set -euo pipefail
# Configuration
SOURCE_URL="https://staging.example.com"
TARGET_URL="https://production.example.com"
BACKUP_DIR="/backups/migrations"
LOG_FILE="/var/log/wp-migration.log"
# Logging
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $@" | tee -a "$LOG_FILE"
}
# Error handler
error_handler() {
log "ERROR: Migration failed at line $1"
log "Rolling back to previous state..."
if [ -f "$ROLLBACK_BACKUP" ]; then
wp db import "$ROLLBACK_BACKUP" && log "β Rollback successful"
fi
exit 1
}
trap 'error_handler ${LINENO}' ERR
# Start migration
log "=== WordPress Migration Started ==="
# Validate preconditions
log "Validating environment..."
wp core is-installed || { log "ERROR: WordPress not installed"; exit 1; }
wp db check || { log "ERROR: Database connection failed"; exit 1; }
# Create backup directory
mkdir -p "$BACKUP_DIR"
# Backup current state
log "Creating rollback backup..."
ROLLBACK_BACKUP="$BACKUP_DIR/rollback-$(date +%Y%m%d-%H%M%S).sql.gz"
wp db export "$ROLLBACK_BACKUP" || { log "ERROR: Backup failed"; exit 1; }
log "β Rollback backup created: $ROLLBACK_BACKUP"
# Verify backup
BACKUP_SIZE=$(stat -c%s "$ROLLBACK_BACKUP")
if [ "$BACKUP_SIZE" -lt 1000 ]; then
log "ERROR: Backup file too small, aborting"
exit 1
fi
# Perform search-replace (dry run first)
log "Testing URL replacement..."
if ! wp search-replace "$SOURCE_URL" "$TARGET_URL" --dry-run --report; then
log "ERROR: Dry run failed"
exit 1
fi
# Execute actual replacement
log "Executing URL replacement..."
wp search-replace "$SOURCE_URL" "$TARGET_URL" --report
# Verify replacement
REMAINING=$(wp search-replace "$SOURCE_URL" "$TARGET_URL" --dry-run --report | grep -c "$SOURCE_URL" || true)
if [ "$REMAINING" -gt 0 ]; then
log "WARNING: Some URLs may not have been replaced"
fi
# Update WordPress options
log "Updating WordPress options..."
wp option update home "$TARGET_URL"
wp option update siteurl "$TARGET_URL"
# Clear caches
log "Clearing caches..."
wp cache flush
wp rewrite flush
log "=== Migration Completed Successfully ==="
log "Rollback backup available at: $ROLLBACK_BACKUP"Safe Plugin Update with Fallback
#!/bin/bash
set -euo pipefail
BACKUP_FILE="/tmp/before-plugin-update-$$.sql.gz"
# Cleanup function
cleanup() {
rm -f "$BACKUP_FILE"
}
trap cleanup EXIT
# Error handler
error_handler() {
echo "ERROR: Plugin update failed, restoring backup..."
if [ -f "$BACKUP_FILE" ]; then
wp db import "$BACKUP_FILE" && echo "β Database restored"
fi
exit 1
}
trap error_handler ERR
# Backup database
echo "Creating safety backup..."
wp db export "$BACKUP_FILE"
# Check for available updates
UPDATES=$(wp plugin list --update=available --format=count)
if [ "$UPDATES" -eq 0 ]; then
echo "No plugin updates available"
exit 0
fi
echo "$UPDATES plugin(s) have updates available"
# Update plugins
echo "Updating plugins..."
wp plugin update --all
# Verify WordPress still works
echo "Verifying WordPress installation..."
wp core is-installed || error_handler
echo "β All plugins updated successfully"
echo "Backup file will be deleted on exit"Next Steps
You now have professional error handling skills for WP-CLI Bash scripts.
Recommended Learning Path
Week 1: Basic error handling
- Implement exit code checking
- Add input validation
- Use set -euo pipefail
Week 2: Advanced trapping
- Create cleanup functions
- Implement error handlers
- Build rollback mechanisms
Week 3: Logging and monitoring
- Add comprehensive logging
- Set up email notifications
- Create error tracking
Week 4: Production hardening
- Review all scripts for error handling
- Create script templates
- Document recovery procedures
Advanced Topics
- Bash Script Testing – Unit testing for Bash scripts
- Monitoring and Alerting – Production script monitoring
- Incident Response – Handling script failures in production
Get More Resources
Download error handling templates including:
- Production-ready script templates
- Error handling checklist
- Common error patterns
- Weekly WP-CLI tutorials
- Advanced scripting techniques
- DevOps best practices
Conclusion
Proper error handling transforms fragile scripts into production-ready automation that you can trust with critical WordPress operations.
What we covered:
β Exit codes and error detection fundamentals β Validation and precondition checking β Error trapping and automatic cleanup with trap β Input validation and argument parsing β Comprehensive logging and error reporting β Production-ready error handling patterns
Master these techniques, and youβll write WordPress automation scripts that gracefully handle failures, protect your data, and make debugging trivial.
Ready for more? Learn advanced Bash scripting patterns or WP-CLI script testing.
Questions about error handling in WP-CLI scripts? Drop a comment below!
Found this helpful? Share with other WordPress developers.
