Created
July 30, 2020 18:34
-
-
Save tylercubell/05c90700a917cf679f481a5ced48bdac to your computer and use it in GitHub Desktop.
WordPress backup script.
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
#!/bin/bash | |
# Variables. | |
backup_dir="backups" | |
files_dir="/var/www/yoursite" # Don't add trailing slash. | |
max_backups=14 # Two weeks. | |
database_name="yoursite" | |
timezone="US/Eastern" | |
# Check if script is running as root. | |
if [ "$EUID" -ne 0 ]; then | |
echo "Please run as root." | |
exit | |
fi | |
# Automatically create cron entry. | |
path_to_script=$(realpath $BASH_SOURCE) | |
filename=`basename "$0"` | |
# If cron entry doesn't exist. | |
if ! crontab -l | grep -q $filename; then | |
echo "Adding cron entry..." | |
crontab -l > cron | |
if [[ ! -f "cron" ]]; then | |
echo "Unable to create cron file." | |
exit | |
fi | |
# Every day at 3 AM. | |
echo "0 3 * * * $path_to_script" >> cron | |
crontab cron | |
rm cron | |
fi | |
# Sanity checks. | |
if [ "$backup_dir" = "" ]; then | |
echo "Backup directory can't be empty." | |
exit | |
elif [ "$backup_dir" = "/" ]; then | |
echo "Backup directory can't be root directory." | |
exit | |
fi | |
if [[ ! -d "$files_dir" ]]; then | |
echo "Files directory doesn't exist." | |
exit | |
fi | |
mysql_data_dir=$(mysql -N -B -e "select @@datadir;") | |
if [[ ! -d "$mysql_data_dir$database_name" ]]; then | |
echo "Database doesn't exist." | |
exit | |
fi | |
# Create backup directory if it doesn't already exist. | |
mkdir -p $backup_dir | |
if [[ ! -d "$backup_dir" ]]; then | |
echo "Unable to create backup directory." | |
exit | |
fi | |
# Remove old backups. | |
while true; do | |
# Count number of backup files in backups directory. | |
backup_files=($backup_dir/*.tar.gz) | |
backup_count=${#backup_files[@]} | |
# Number of backups exceeds limit. | |
if [ "$backup_count" -gt "$max_backups" ]; then | |
echo "Backup limit exceeded." | |
oldest_file=$(find $backup_dir -type f -name '*.tar.gz' -printf '%T+ %f\n' | sort | head -n 1 | awk '{print $2}') | |
# Sanity check. Make sure file extension is correct before deleting. | |
if [ "${oldest_file: -7}" = ".tar.gz" ]; then | |
echo "Deleting $oldest_file..." | |
rm -f $backup_dir/$oldest_file | |
fi | |
# Backup limit not exceeded. | |
else | |
break | |
fi | |
done | |
# Create temporary directory for backup. | |
uuid=$(uuidgen) | |
now=$(TZ=":$timezone" date) | |
now=${now// /-} # Replace spaces with hyphens. | |
now=${now//:/-} # Replace colons with hyphens. | |
temp_dir="${now}_$uuid" | |
mkdir -p $backup_dir/$temp_dir | |
if [[ ! -d "$backup_dir/$temp_dir" ]]; then | |
echo "Unable to create temporary directory." | |
exit | |
fi | |
# Backup MySQL database. | |
echo "Dumping MySQL database..." | |
mysqldump $database_name > $backup_dir/$temp_dir/database.sql | |
# Copy files before archiving. | |
# Avoids tar "file changed as we read it" error for live sites. | |
echo "Copying web files..." | |
mkdir -p $backup_dir/$temp_dir/files | |
rsync -a $files_dir/ $backup_dir/$temp_dir/files | |
# Backup files. | |
echo "Archiving web files..." | |
# Add web files to 'files' folder in archive. | |
tar -C $backup_dir/$temp_dir -cf $backup_dir/$temp_dir/backup.tar files | |
# Append database to end of archive. | |
echo "Append database to archive..." | |
tar -C $backup_dir/$temp_dir -rf $backup_dir/$temp_dir/backup.tar database.sql | |
# Compress archive with gzip. | |
echo "Compressing archive..." | |
gzip $backup_dir/$temp_dir/backup.tar | |
# Clean up temp files. | |
echo "Cleaning up..." | |
# Move archive to main backups directory. | |
mv $backup_dir/$temp_dir/backup.tar.gz $backup_dir/$temp_dir.tar.gz | |
# Remove temp directory. | |
# Todo: add sanity check to make sure fs isn't wiped out. | |
rm -rf $backup_dir/$temp_dir | |
# Done. | |
echo "Done!" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Todo:
See: