If you’re writing WordPress automation scripts with WP-CLI, you’ve probably found yourself copy-pasting the same code blocks over and over. Database exports, plugin updates, backup routines—the same patterns repeat across different scripts.
- Why Use Functions in Bash Scripts?
- Basic Function Syntax {#basic-syntax}
- Parameter Handling in Functions
- Return Values and Exit Codes
- Error Handling Best Practices
- Real-World WordPress Functions {#wordpress-functions}
- Building a Function Library {#function-library}
- Advanced Patterns {#advanced-patterns}
- Testing Your Functions {#testing}
- Next Steps
- Conclusion
This is where Bash functions become your secret weapon.
In this guide, you’ll learn how to write reusable, production-ready Bash functions for WordPress automation. We’ll cover parameter validation, error handling, logging, and real-world examples you can use immediately in your WP-CLI scripts.
Why Use Functions in Bash Scripts?
Functions are reusable blocks of code that make your scripts:
More Maintainable: Fix a bug once in the function, not in 10 different scripts.
Easier to Read: backup_wordpress_database is clearer than 20 lines of inline code.
More Testable: Test individual functions independently.
DRY (Don’t Repeat Yourself): Write once, use everywhere.
Professional: Production-ready scripts use functions extensively.
Before Functions: Repetitive Code
Here’s what many WordPress automation scripts look like without functions:
#!/bin/bash
# Script 1: Backup site A
cd /var/www/siteA
wp db export /backups/siteA-$(date +%Y%m%d).sql
tar -czf /backups/siteA-files-$(date +%Y%m%d).tar.gz .
echo "Backup completed for Site A"
# Script 2: Backup site B (almost identical!)
cd /var/www/siteB
wp db export /backups/siteB-$(date +%Y%m%d).sql
tar -czf /backups/siteB-files-$(date +%Y%m%d).tar.gz .
echo "Backup completed for Site B"
This violates DRY principles and becomes a maintenance nightmare.
After Functions: Clean and Reusable
With functions, the same logic becomes:
#!/bin/bash
# Reusable function
backup_wordpress() {
local wp_path=$1
local backup_dir=$2
local site_name=$(basename "$wp_path")
local timestamp=$(date +%Y%m%d)
cd "$wp_path" || return 1
wp db export "${backup_dir}/${site_name}-${timestamp}.sql" || return 1
tar -czf "${backup_dir}/${site_name}-files-${timestamp}.tar.gz" . || return 1
echo "Backup completed for ${site_name}"
}
# Use the function
backup_wordpress /var/www/siteA /backups
backup_wordpress /var/www/siteB /backups
backup_wordpress /var/www/siteC /backups
One function, multiple uses. Change the backup logic once, and all three sites benefit.
Basic Function Syntax {#basic-syntax}
Bash functions can be defined in two ways:
Method 1: Using the function Keyword
function my_function() {
echo "Hello from my function"
}
Method 2: Without the function Keyword (POSIX-compliant)
my_function() {
echo "Hello from my function"
}
Both work identically. Method 2 is more portable and preferred for production scripts.
Calling Functions
Simply use the function name:
my_function # Calls the function
Example: Simple WordPress Function
#!/bin/bash
# Function to check WordPress version
check_wp_version() {
wp core version
}
# Call it
check_wp_version
Output:
6.4.2
Parameter Handling in Functions
Functions accept parameters just like scripts. Parameters are accessed using $1, $2, $3, etc.
Basic Parameters
greet_user() {
local name=$1
echo "Hello, ${name}!"
}
greet_user "John" # Output: Hello, John!
Multiple Parameters
update_wordpress() {
local wp_path=$1
local backup=$2
cd "$wp_path" || return 1
if [ "$backup" = "yes" ]; then
wp db export backup.sql
fi
wp core update
}
# Usage
update_wordpress /var/www/html yes
Parameter Variables
Bash provides special variables for working with parameters:
$#– Number of parameters$@– All parameters as separate strings$*– All parameters as single string$1, $2, ...– Individual parameters
WordPress Example: Plugin Update Function
update_plugin() {
local wp_path=$1
local plugin_name=$2
echo "Updating plugin: ${plugin_name} at ${wp_path}"
wp plugin update "$plugin_name" --path="$wp_path"
}
# Usage
update_plugin /var/www/html woocommerce
update_plugin /var/www/html yoast-seo
Return Values and Exit Codes
Bash functions don’t return values like other programming languages. Instead, they use:
- Exit codes (0 for success, non-zero for failure)
- Echo statements (output that can be captured)
Exit Codes with return
check_wordpress_exists() {
local wp_path=$1
if [ -f "${wp_path}/wp-config.php" ]; then
return 0 # Success
else
return 1 # Failure
fi
}
# Usage
if check_wordpress_exists /var/www/html; then
echo "WordPress found!"
else
echo "WordPress not found"
fi
Best Practice: Always return 0 for success, 1+ for errors. This follows Unix conventions and works with if statements.
Returning Values via Echo
get_wordpress_version() {
local wp_path=$1
wp core version --path="$wp_path"
}
# Capture output
version=$(get_wordpress_version /var/www/html)
echo "WordPress version: ${version}"
Combining Both Approaches
backup_database() {
local wp_path=$1
local backup_file=$2
# Perform backup
if wp db export "$backup_file" --path="$wp_path" 2>/dev/null; then
echo "$backup_file" # Return filename
return 0 # Success exit code
else
echo "" # Return empty string
return 1 # Failure exit code
fi
}
# Usage
if backup_file=$(backup_database /var/www/html "/backups/db.sql"); then
echo "Backup successful: ${backup_file}"
else
echo "Backup failed"
fi
Error Handling Best Practices
Production-ready functions need robust error handling. Here’s how to do it right.
Use set -e Cautiously
#!/bin/bash
set -e # Exit on any error
# This will exit the entire script if wp fails
wp plugin update --all
Problem: set -e exits the entire script on first error, which might not be what you want in functions.
Better approach: Handle errors explicitly in functions.
Check Command Success
update_all_plugins() {
local wp_path=$1
if ! wp plugin update --all --path="$wp_path"; then
echo "ERROR: Plugin update failed" >&2
return 1
fi
echo "All plugins updated successfully"
return 0
}
Validate Parameters
backup_wordpress() {
local wp_path=$1
local backup_dir=$2
# Validate parameters exist
if [ -z "$wp_path" ] || [ -z "$backup_dir" ]; then
echo "ERROR: Missing parameters" >&2
echo "Usage: backup_wordpress <wp_path> <backup_dir>" >&2
return 1
fi
# Validate WordPress directory
if [ ! -f "${wp_path}/wp-config.php" ]; then
echo "ERROR: Not a WordPress installation: ${wp_path}" >&2
return 1
fi
# Validate backup directory
if [ ! -d "$backup_dir" ]; then
echo "ERROR: Backup directory doesn't exist: ${backup_dir}" >&2
return 1
fi
# Perform backup
# ... backup logic here ...
}
Use Error Messages to STDERR
Send errors to stderr (file descriptor 2) instead of stdout:
log_error() {
echo "[ERROR] $*" >&2
}
log_info() {
echo "[INFO] $*"
}
# Usage
if ! wp core update; then
log_error "WordPress core update failed"
return 1
fi
log_info "WordPress updated successfully"
This allows users to separate errors from normal output:
./script.sh 2>errors.log # Only errors go to file
./script.sh 2>&1 | grep ERROR # Search errors
Real-World WordPress Functions {#wordpress-functions}
Let’s build production-ready functions you can use immediately.
Function 1: WordPress Site Backup
#!/bin/bash
backup_wordpress_site() {
local wp_path=$1
local backup_dir=$2
local timestamp=$(date +%Y%m%d_%H%M%S)
local site_name=$(basename "$wp_path")
# Validate inputs
if [ -z "$wp_path" ] || [ -z "$backup_dir" ]; then
echo "ERROR: Usage: backup_wordpress_site <wp_path> <backup_dir>" >&2
return 1
fi
if [ ! -f "${wp_path}/wp-config.php" ]; then
echo "ERROR: Invalid WordPress path: ${wp_path}" >&2
return 1
fi
# Create backup directory if needed
mkdir -p "$backup_dir"
# Backup database
local db_file="${backup_dir}/${site_name}_db_${timestamp}.sql"
echo "Backing up database..."
if ! wp db export "$db_file" --path="$wp_path" --quiet; then
echo "ERROR: Database backup failed" >&2
return 1
fi
# Compress database
gzip "$db_file"
echo "Database backed up: ${db_file}.gz"
# Backup files
local files_archive="${backup_dir}/${site_name}_files_${timestamp}.tar.gz"
echo "Backing up files..."
if ! tar -czf "$files_archive" -C "$(dirname $wp_path)" "$(basename $wp_path)" 2>/dev/null; then
echo "ERROR: File backup failed" >&2
return 1
fi
echo "Files backed up: ${files_archive}"
echo "Backup completed successfully"
return 0
}
# Usage
backup_wordpress_site /var/www/html /backups
Function 2: Bulk Plugin Update with Verification
update_plugins_safe() {
local wp_path=$1
# Validation
if [ ! -f "${wp_path}/wp-config.php" ]; then
echo "ERROR: Invalid WordPress path" >&2
return 1
fi
echo "Checking for plugin updates..."
local updates=$(wp plugin list --update=available --path="$wp_path" --format=count)
if [ "$updates" -eq 0 ]; then
echo "All plugins are up to date"
return 0
fi
echo "Found ${updates} plugin(s) to update"
# Backup database before updates
local backup_file="/tmp/pre-update-backup-$(date +%s).sql"
echo "Creating safety backup..."
if ! wp db export "$backup_file" --path="$wp_path" --quiet; then
echo "ERROR: Safety backup failed, aborting" >&2
return 1
fi
echo "Updating plugins..."
if wp plugin update --all --path="$wp_path"; then
echo "Plugins updated successfully"
rm -f "$backup_file" # Clean up backup if successful
return 0
else
echo "ERROR: Plugin update failed" >&2
echo "Safety backup available at: ${backup_file}"
return 1
fi
}
# Usage
update_plugins_safe /var/www/html
Function 3: WordPress Health Check
wordpress_health_check() {
local wp_path=$1
local errors=0
echo "Running WordPress health check for: ${wp_path}"
echo "=============================================="
# Check 1: WordPress core
echo -n "WordPress Core: "
if wp core verify-checksums --path="$wp_path" &>/dev/null; then
echo "✓ OK"
else
echo "✗ FAILED"
((errors++))
fi
# Check 2: Database
echo -n "Database Connection: "
if wp db check --path="$wp_path" &>/dev/null; then
echo "✓ OK"
else
echo "✗ FAILED"
((errors++))
fi
# Check 3: Plugin updates
echo -n "Plugin Updates: "
local plugin_updates=$(wp plugin list --update=available --path="$wp_path" --format=count)
if [ "$plugin_updates" -eq 0 ]; then
echo "✓ All up to date"
else
echo "⚠ ${plugin_updates} update(s) available"
fi
# Check 4: Theme updates
echo -n "Theme Updates: "
local theme_updates=$(wp theme list --update=available --path="$wp_path" --format=count)
if [ "$theme_updates" -eq 0 ]; then
echo "✓ All up to date"
else
echo "⚠ ${theme_updates} update(s) available"
fi
# Check 5: Core version
local wp_version=$(wp core version --path="$wp_path")
echo "WordPress Version: ${wp_version}"
echo "=============================================="
if [ $errors -eq 0 ]; then
echo "Health check passed"
return 0
else
echo "Health check failed with ${errors} error(s)"
return 1
fi
}
# Usage
wordpress_health_check /var/www/html
Building a Function Library {#function-library}
Create a reusable library that you can source into any WordPress automation script.
Create the Library File
# Save as: ~/wp-functions.sh
#!/bin/bash
#
# WordPress Automation Function Library
# Source this file in your scripts: source ~/wp-functions.sh
#
# Color codes for output
RED='3[0;31m'
GREEN='3[0;32m'
YELLOW='3[1;33m'
NC='3[0m' # No Color
# Logging functions
log_info() {
echo -e "${GREEN}[INFO]${NC} $*"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $*" >&2
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $*"
}
# Check if path is valid WordPress installation
is_wordpress() {
local wp_path=$1
[ -f "${wp_path}/wp-config.php" ]
}
# Get WordPress version
get_wp_version() {
local wp_path=$1
wp core version --path="$wp_path" 2>/dev/null
}
# Check if plugin is installed
has_plugin() {
local wp_path=$1
local plugin_name=$2
wp plugin is-installed "$plugin_name" --path="$wp_path" 2>/dev/null
}
# Safely update WordPress core
safe_core_update() {
local wp_path=$1
if ! is_wordpress "$wp_path"; then
log_error "Not a WordPress installation: ${wp_path}"
return 1
fi
local current_version=$(get_wp_version "$wp_path")
log_info "Current version: ${current_version}"
# Backup first
log_info "Creating backup..."
local backup_file="/tmp/wp-backup-$(date +%s).sql"
if ! wp db export "$backup_file" --path="$wp_path" --quiet; then
log_error "Backup failed"
return 1
fi
# Update
log_info "Updating WordPress core..."
if wp core update --path="$wp_path"; then
local new_version=$(get_wp_version "$wp_path")
log_info "Updated from ${current_version} to ${new_version}"
rm -f "$backup_file"
return 0
else
log_error "Update failed. Backup saved at: ${backup_file}"
return 1
fi
}
Using the Library
Create a script that sources the library:
#!/bin/bash
# my-script.sh
# Load function library
source ~/wp-functions.sh
# Use the functions
log_info "Starting WordPress maintenance..."
if is_wordpress /var/www/html; then
log_info "WordPress found"
safe_core_update /var/www/html
else
log_error "WordPress not found"
exit 1
fi
This approach keeps your scripts clean and maintainable. Update the library once, and all scripts benefit.
Advanced Patterns {#advanced-patterns}
Pattern 1: Functions with Named Parameters
backup_wordpress() {
# Parse named parameters
local wp_path=""
local backup_dir=""
local include_uploads=true
while [[ $# -gt 0 ]]; do
case $1 in
--path)
wp_path="$2"
shift 2
;;
--backup-dir)
backup_dir="$2"
shift 2
;;
--no-uploads)
include_uploads=false
shift
;;
*)
echo "Unknown option: $1" >&2
return 1
;;
esac
done
# Use the parameters
echo "Path: ${wp_path}"
echo "Backup dir: ${backup_dir}"
echo "Include uploads: ${include_uploads}"
}
# Usage
backup_wordpress --path /var/www/html --backup-dir /backups --no-uploads
Pattern 2: Functions with Default Parameters
update_wordpress() {
local wp_path=${1:-/var/www/html} # Default to /var/www/html
local backup=${2:-yes} # Default to yes
echo "Path: ${wp_path}"
echo "Backup: ${backup}"
}
# Call with defaults
update_wordpress
# Call with custom values
update_wordpress /var/www/mysite no
Pattern 3: Array Return Values
get_outdated_plugins() {
local wp_path=$1
wp plugin list --update=available --path="$wp_path" --field=name
}
# Capture into array
mapfile -t plugins < <(get_outdated_plugins /var/www/html)
# Loop through results
for plugin in "${plugins[@]}"; do
echo "Outdated: ${plugin}"
done
Testing Your Functions {#testing}
Always test functions before using in production.
Manual Testing Script
#!/bin/bash
# test-functions.sh
source ~/wp-functions.sh
echo "Testing WordPress functions..."
echo "=============================="
# Test 1: is_wordpress
echo "Test 1: is_wordpress"
if is_wordpress /var/www/html; then
echo "✓ PASS"
else
echo "✗ FAIL"
fi
# Test 2: get_wp_version
echo "Test 2: get_wp_version"
version=$(get_wp_version /var/www/html)
if [ -n "$version" ]; then
echo "✓ PASS: Version ${version}"
else
echo "✗ FAIL"
fi
# Add more tests...
Automated Testing with BATS
For serious projects, use BATS (Bash Automated Testing System):
# Install BATS
git clone https://github.com/bats-core/bats-core.git
cd bats-core
./install.sh /usr/local
# Create test file: test-wp-functions.bats
#!/usr/bin/env bats
load ~/wp-functions.sh
@test "is_wordpress returns true for valid path" {
run is_wordpress /var/www/html
[ "$status" -eq 0 ]
}
@test "is_wordpress returns false for invalid path" {
run is_wordpress /tmp
[ "$status" -eq 1 ]
}
# Run tests
bats test-wp-functions.bats
Next Steps
You now know how to write reusable Bash functions for WordPress automation. Here’s what to learn next:
Related Guides
- Bulletproof Error Handling in Bash Scripts for WP-CLI – Take error handling to the next level
- How to Parse Command Line Arguments in WP-CLI Bash Scripts – Make your functions accept complex parameters
- Professional Logging and Debugging for WP-CLI Automation Scripts – Add production-grade logging
Practice Projects
Build a function library with these functions:
- Database backup and restore
- Plugin/theme management
- User management
- Content import/export
- Security hardening
Create a WordPress maintenance script that:
- Uses multiple functions from your library
- Accepts command-line arguments
- Has proper error handling
- Outputs colored logs
Join WPCLI Mastery
Want to master WordPress automation with battle-tested patterns and real-world projects?
Join the WPCLI Mastery waitlist and get:
- Free WordPress backup automation script (production-ready functions included)
- Access to complete function library
- Early bird course pricing ($99 vs $199)
Conclusion
Bash functions transform messy WordPress automation scripts into clean, maintainable, professional code. The patterns you learned here—parameter validation, error handling, return values—are the foundation of production-ready automation.
Key takeaways:
- Functions eliminate code duplication
- Always validate parameters
- Use return codes (0 = success, 1+ = failure)
- Handle errors explicitly
- Build a reusable function library
- Test your functions before production use
Start building your function library today. Every reusable function you write saves time on every future script.
Ready to build advanced WordPress automation? Check out our guide on automating WordPress backups with WP-CLI, which uses these function patterns in a complete project.
Questions about Bash functions for WordPress? Drop a comment below!
Found this helpful? Share it with other WordPress developers learning automation.

Leave a Reply