Bash scripts: WordPress Restore

WordPress Logo created from https://en.wikipedia.org/wiki/WordPress#/media/File:WordPress_logo.svg using GIMP.

1: Introduction
2: Requirements
3: Script
4: The Devil

1: Introduction

Bash script WordPress Restore is the conjugate tool for restoring from a backup created by the WordPress Backup script. WordPress restore is one of the most important tasks for a WordPress site administrator for obvious reasons. The script presented in this post guarantees a way to “reproducibly restore” a WordPress site and it’s accompanying database. The statement is quoted because there is a caveat. Such is only true on the same hardware and configuration, for the most part.

The reasons for that is that the devil is in the details of a WordPress restore. This is especially true if you are going from one platform to another, i.e. from an Amazon EC2 instance to a locally hosted test server running Ubuntu on older HP workstation hardware. We’ll get to that at the end of the discourse.

This post is part of the Bash scripts for fun and leisure series.

2: Requirements

The requirements to restore a WordPress website are:

  • You have sudo on the server.
  • You have the proper access and permissions to write the document root ( /var/www/html ) of the WordPress installation.
  • The ability to change permissions and ownership within document root, i.e. sudo.
  • You can execute tar, gzip, and mysql with the necessary permissions.
  • The restore archive lives in the same folder as the script, or the full path to the archive file is passed to the script.
  • You have appropriate database permissions to write/modify/drop a database. However the best way to restore the database is via the administrator/root database user (not to be confused with system root).

3: Script

The script is a fairly straightforward reversal of the backup script. It includes consistency checking the file and database backups.

#! /bin/bash
# DO NOT LEAK THIS SCRIPT
# IT HAS CRITICAL DATABASE DATA!

# Configure variables.
_sn=$(date +"%Y%m%dT%H%M%S")
_default="\e[39m"
_red="\e[31m"
_green="\e[32m"
_magenta="\e[35m"
_backup_owner=<the account that owns the backups>
_db_user=<the database username>
_db_pwd=<the database password, enclosed in double quotes>
_db_name=<the name of your database>
_sitename=<your site name or whatever you want as prefix>

# DO IT FOR SITE!
echo -e $_magenta$_sitename" Website Code Restore"
echo -e "Version: 20230331" $_default
# Check if we have a filename passed.
if [ $# -ne 1 ]; then
  echo "Usuage: restore_wordpress.sh <backup file name without extension>"
  exit
fi
_backupCF=$1'.tgz'
_backupCFCS=$1'.tgz.asc'
_backupDB=$1'.sql.gz'
_backupDBCS=$1'.sql.gz.asc'
# Check if the files are present.
for i in $_backupCF $_backupCFCS $_backupDB $_backupDBCS
do
	if [ ! -f $i ]; then
		echo -e $_red"Missing file: "$_default$i
		echo -e $_red"Can't continue without file!"$_default
		exit
	fi
done
echo -e $_red"Checking file integrity..."$_default
for i in $_backupCFCS $_backupCFCS
do
	sha256sum --status -c $i
	if [ $? -ne 0 ]; then
		echo -e $_red" File "$_default$i$_red" failed verification."$_default
		echo -e $_red"Can't continue with corrupted file."$_default
		exit
	fi
done
echo -e $_red"Starting website code restore..."$_defaultp
pushd /var/www
sudo tar --overwrite --recursive-unlink -xzf  $_backupCF
if [ $? -ne 0 ]; then
		echo -e $_red"Errors detected in code restore."$_default
		echo -e $_red"Can't continue because code may be corrupted"$_default
		popd
		exit
fi
popd
echo -e $_green"Done restoring "$_sitename" code!"$_default
echo ""
# DO IT FOR DATABASE!
echo -e $_magenta$_sitename" Website Database Restore"
echo -e "Version: 20230331"$_default
gunzip $_backupDB
if [ $? -ne 0 ]; then
		echo -e $_red"Errors detected in unpacking database archive."$_default
		echo -e $_red"Can't continue because database may be corrupted"$_default
		exit
fi
_dbsqlfile=$1'.sql'
mysql -p$_db_pwd  -u $_db_user $_db_name < $_dbsqlfile
if [ $? -ne 0 ]; then
		echo -e $_red"Errors detected in restoring the database"$_default
		echo -e $_red"Site may be corrupted!"$_default
		exit
fi
echo -e $_green"Done restoring "$_sitename" database!"$_default
echo -e $_green"*** ALL DONE ***"$_default

4: The Devil

There are several details that can bite you when restoring a site. The devil appears when restoring to something other than the original, or a very similar, server. These issues result from differences in server configurations, such as which Apache modules are present and active. Those issues also apply to other components of the LAMP stack. Harder to debug are issues occurring from the contents of the database. Plugins may use restored database data in unexpected or incorrect ways. Sometimes, in the case of migration or replication to a significantly different server, substantial modification of the configuration and database may be necessary, including disabling of certain WordPress plugins, i.e. the Google reCAPTCHA plugin. Some examples of the issues that can crop up are:

  • Different server versions / active modules and/or configurations.
  • Different database versions / configurations / permissions and/or ports.
  • Different web root locations.
  • Broken re-directions or blocked logins because of the local URL being different from the original server URL. I.e. example.com vs. test.example.com.
  • Administrator email addresses may be different, i.e. admin@example.com vs. admin@test.example.com
  • Database entries referencing incorrect objects or objects that no longer exist.