-
-
Save grantnorwood/14612f596d96973b14caea41fd45f832 to your computer and use it in GitHub Desktop.
Backup and update a Wordpress Site using wp-cli
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
########################################################################## | |
# Shellscript : Backup and update WordPress using wp-cli | |
# Author : Grant Norwood <grantnorwood.com> | |
# Original Author : Paco Orozco <paco@pacoorozco.info> | |
# Requires : wp-cli | |
########################################################################## | |
# Changelog | |
# 20220430: 2.0 | |
# Adds a user-specified option for forcing backup & updates | |
# 20170125: 1.0 | |
# Adds a default option to upgrade only when it's needed. | |
# 20161220: 0.1 | |
# Inital release | |
########################################################################## | |
########################################################################## | |
# Configuration Section | |
########################################################################## | |
# | |
########################################################################## | |
# DO NOT MODIFY BEYOND THIS LINE | |
########################################################################## | |
# Program name and version | |
PN=$( basename "$0" ) | |
VER='1.0' | |
# Script exits immediately if any command within it exits with a non-zero status. | |
set -o errexit | |
# Script will catch the exit status of a previous command in a pipe. | |
set -o pipefail | |
# Script exits immediately if tries to use an undeclared variables. | |
set -o nounset | |
# Uncomment this to enable debug | |
# set -o xtrace | |
# Get data in dd-mm-yyyy format | |
TIMESTAMP=$( date +"%Y%m%d-%H%M" ) | |
# Set verbose mode | |
VERBOSE=false | |
WP_PATH="" | |
BACKUP_PATH="" | |
NUM_OF_BACKUPS=0 | |
WP_CLI="wp" | |
FORCE_BACKUP=false | |
WXR=false | |
# Ansi color code variables | |
red="\e[0;91m" | |
blue="\e[0;94m" | |
expand_bg="\e[K" | |
blue_bg="\e[0;104m${expand_bg}" | |
red_bg="\e[0;101m${expand_bg}" | |
green_bg="\e[0;102m${expand_bg}" | |
green="\e[0;92m" | |
white="\e[0;97m" | |
bold="\e[1m" | |
uline="\e[4m" | |
reset="\e[0m" | |
### | |
# Examples | |
### | |
# # horizontally expanded backgrounds | |
# echo -e "${blue_bg}${reset}" | |
# echo -e "${red_bg}${reset}" | |
# echo -e "${green_bg}${reset}" | |
# echo "" | |
# # colored text | |
# echo -e "${red}Hello World!${reset}" | |
# echo "" | |
# # bold colored text | |
# echo -e "${red}${bold}Hello World!${reset}" | |
# echo "" | |
# # underlined colored text | |
# echo -e "${red}${uline}Hello World!${reset}" | |
# echo "" | |
# # ansi across multiple lines | |
# echo -e "${green}This is a sentence across" | |
# echo "three lines to show how an ansi color" | |
# echo -e "works across multiple lines with echo.${reset}" | |
# echo "" | |
# # combining ansi in one line | |
# echo -e "${red}This sentence ${green}displays ${blue}ansi code used in ${white}${bold}combination.${reset}" | |
########################################################################## | |
# Functions | |
########################################################################## | |
function warn () { | |
if [ "${VERBOSE}" = true ] | |
then | |
if [ "$1" = "-n" ] | |
then | |
shift; echo -n "$@" | |
else | |
echo "$@" | |
fi | |
fi | |
} | |
function crit () { | |
local ERROR=0 | |
[ "$1" = "-e" ] && shift; ERROR=$1; shift | |
echo >&2 -e "${PN}: $@" | |
[ ${ERROR} ] && exit ${ERROR} | |
} | |
function check-requirements () { | |
# Check if wp-cli is installed. | |
if ! hash ${WP_CLI} 2>/dev/null ; then | |
crit -e 1 "We require wp-cli.\nFor more info visit wp-cli.org or github.com/wp-cli/wp-cli/wiki." | |
fi | |
} | |
function usage () { | |
# Variables for formatting | |
local U=$(tput smul) # Underline | |
local RU=$(tput rmul) # Remove underline | |
local B=$(tput bold) # Bold | |
local N=$(tput sgr0) # Normal | |
cat <<-EOF | |
${B}Usage:${N} | |
${B}${PN}${N} -p ${U}directory${RU} [-b ${U}directory${RU}] [options]... | |
${B}Options:${N} | |
${B}-f${N} Force backup even if the WordPress site is updated | |
${B}-h${N} Display this help message | |
${B}-v${N} Enable verbose mode | |
${B}-p${N} ${U}directory${RU} | |
Path to WordPress files. This is a required flag. | |
${B}-b${N} ${U}backup_dir${RU} | |
Backup WP installation into a ${U}backup_dir${RU} before updating. Backs up | |
both the database and files. Will be stored in the following format: | |
${U}backup_directory${RU} | |
├── wp-backup_YYYY-MM-DD_HH:MM:SS | |
│ ├── database.sql | |
│ └── files.tar.gz | |
└── wp-backup... | |
Without this option the script will keep backups on ${U}directory/backups${RU}. | |
${B}-n${N} ${U}number${RU} | |
Number of backups to keep if ${B}-b${N} is specified. Useful to keep the | |
backups directory clean, in case this script is run as a cron job. | |
Without this option the script will keep unlimited backups. | |
${B}-w${N} Generate a wxr (WordPress Extended RSS) file if ${B}-b${N} is specified. | |
This file contains all your posts and is useful if you want to | |
quickly migrate to wordpress.com. Otherwise it is redundant as the | |
${B}-b${N} option already exports your database. | |
${B}Examples:${N} | |
${PN} ${B}-p${N} ${U}/var/www/wp${RU} | |
Minimal options. Will update WordPress installation in the specified | |
directory. Will backup in /var/www/wp/backups. | |
${PN} ${B}-p${N} ${U}/var/www/wp${RU} ${B}-b${N} ${U}~/backups${RU} ${B}-n${N} ${U}5${RU} | |
Same as above but now if there are old backups in the backups directory | |
the script will clean it up leaving only the 5 most recent ones. | |
If there are less than 5 backups, then nothing will happen. | |
EOF | |
} | |
function backup () { | |
echo "" | |
echo -e "${bold}Backing up your site's database & files ...${reset}" | |
local BACKUP_PATH_TIMESTAMP="${BACKUP_PATH}/wp-backup_${TIMESTAMP}" | |
mkdir -p ${BACKUP_PATH_TIMESTAMP} | |
echo -e " • Backing up the database ...${reset}" | |
${WP_CLI} db export ${BACKUP_PATH_TIMESTAMP}/db.sql | |
echo -e " • Backing up site directory ...${reset}" | |
tar -czf ${BACKUP_PATH_TIMESTAMP}/www.tar.gz \ | |
--exclude='**/wp-content/upgrade' \ | |
--exclude='**/wp-content/uploads/backupbuddy_backups' \ | |
--exclude='**/wp-content/uploads/pb_backupbuddy' \ | |
${WP_PATH} \ | |
2>/dev/null | |
if [ $WXR = true ] ; then | |
${WP_CLI} export --dir=${BACKUP_PATH_TIMESTAMP} | |
fi | |
echo -e "✅ ${green}Done!${reset}" | |
} | |
function update () { | |
echo "" | |
echo -e "${bold}Running WordPress updates ...${reset}" | |
echo -e " • Updating core ...${reset}" | |
${WP_CLI} core update | |
echo -e " • Updating plugins ...${reset}" | |
${WP_CLI} plugin update --all | |
echo -e " • Updating themes ...${reset}" | |
${WP_CLI} theme update --all | |
echo -e "✅ ${green}Done!${reset}" | |
} | |
function exit_if_update_is_not_needed () { | |
local NEED_CORE_UPDATE=$( ${WP_CLI} core check-update --format=count ) | |
local NEED_PLUGIN_UPDATE=$( ${WP_CLI} plugin list --update=available --format=count ) | |
if [ -z "${NEED_CORE_UPDATE}" ] && [ "${NEED_PLUGIN_UPDATE}" = "0" ] ; then | |
warn "🤷♂️ This WordPress site is updated. Nothing to do." | |
exit 0 | |
fi | |
echo -e "👉 Updates are available.${reset}" | |
# warn "There are some updates available." | |
} | |
function cleanup () { | |
if [ "${NUM_OF_BACKUPS}" -gt "0" ] ; then | |
echo -e "🗑 ${$bold}Deleting backups greater than ${NUM_OF_BACKUPS} ...${reset}" | |
ls -td ${BACKUP_PATH}/* | awk -v n=${NUM_OF_BACKUPS} 'NR>n' | xargs -r rm -r | |
echo -e "✅ ${green}Done!${reset}" | |
fi | |
} | |
function finish () { | |
echo "" | |
echo -e "🏁 ${bold}Finished!${reset}" | |
echo "" | |
} | |
########################################################################## | |
# Main | |
########################################################################## | |
# Resetting OPTIND is necessary if getopts was used previously in the script. | |
OPTIND=1 | |
# Process command line options | |
while getopts ":hvfwp:b:n:" opt; do | |
case $opt in | |
h) | |
usage | |
;; | |
p) | |
WP_PATH=${OPTARG} | |
;; | |
b) | |
BACKUP_PATH=${OPTARG} | |
;; | |
n) | |
if [ ! $( echo ${OPTARG} | egrep ^[[:digit:]]+$ ) ] ; then | |
crit -e 1 "Bad number of backups to keep" | |
else | |
NUM_OF_BACKUPS=${OPTARG} | |
fi | |
;; | |
w) | |
WXR=true | |
;; | |
v) | |
VERBOSE=true | |
;; | |
f) | |
FORCE_BACKUP=true | |
;; | |
?) | |
crit -e 1 "Invalid option: -${OPTARG}" | |
;; | |
:) | |
crit -e 1 "Option -${OPTARG} requires and arguement" | |
;; | |
esac | |
done | |
# Shift off the options and optional --. | |
shift "$((OPTIND - 1))" | |
# Run appropriate functions based on options provided | |
if [ -z "${WP_PATH}" ] ; then | |
usage | |
exit 1 | |
fi | |
# Set a default Backup path if it hasn't beed defined | |
BACKUP_PATH="${BACKUP_PATH:-${WP_PATH}/backups}" | |
# Set the wp-cli command with WP path | |
WP_CLI="wp --path=${WP_PATH}" | |
check-requirements | |
if [ $FORCE_BACKUP != true ] ; then | |
# Checks if WordPress update is needed. | |
exit_if_update_is_not_needed | |
exit 1 | |
fi | |
# We need to update someting. | |
backup | |
update | |
cleanup | |
finish |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment