Recently, I was doing some research on automatically backing up wordpress database and files. Yes, there are tons of plugins that do a wonderful job of achieving this like the BackUpWordpress plugin that even sends you an email copy of your backup. But as usual, I wanted to find a way to do this without using a plugin. I found that on a linux server, one can use something known as the bash shell script to easily take MySql database backups even of very large databases (This is of-course provided that your server uses the bash shell which is most often the case). A bash script is a list of shell commands written in bash programming language that lets you interact with your linux server and perform a variety of system admin tasks.
To learn more about bash scripts, check out this tutorial on the Linux Documentation Project site.
I found a really good backup script on this forum, made a few modifications to it and also added a few extra lines to delete older backups so the backups do not eat up the server space. I tested this script in a couple of hosting servers and it works great. So here's the tutorial on how this can be done:
This tutorial assumes that you have the following:
- Your site is hosted on a linux server
- Your have CPanel installed on the server
Here's what we will be backing up:
- WordPress database: The wordpress database contains all your text based content including your posts, pages, comments, tags, categories, links etc.
- WordPress Uploads Folder: The uploads folder contains all your images/media files.
- WordPress Theme Folder: The theme folder contains your theme files. This includes all your theme customizations.
Your backups will be compressed using gzip and you will be able to open them using a program like WinRar or Winzip.
Before beginning, here are the steps involved in a nutshell:
- Create a backup folder in the server to save the backups in.
- Create a .sh file with the bash shell script and upload it to the server.
- Create a cron job to call and run this script on a daily basis.
- Download the backed up files and save them locally.
So let's look at these steps in details:
1: Creating the Backup Folder
The first step is to create a backup folder in your server. This is the folder where all your back-up files will be saved. You can create this folder under your server's etc folder or simply create a new folder in your home directory as follows:
Step 1: FTP to your web server. The FTP software I am using is WinSCP.
Step 2: Go to your home directory. The home directory is the directory where your public_html folder is. Refer image below:
Step 3: Create a folder named 'wp_backup' in the home directory as shown in the image above.
2: Adding the Shell Script
We will now create a sh file with the bash shell script and upload it to the server inside our backup folder.
Step 1: Open your text editor (preferably Notepad++ but you can also notepad) and add the following code in it:
#!/bin/bash
# your backups will use these filenames.
db_backup_name="wp-db-backup-"`date "+%Y-%m-%d"`".sql.gz"
wpfiles_backup_name="wp-files-backup-"`date "+%Y-%m-%d"`".tar.gz"
## 1: database connection info. You can get these details from your wp-config file.
db_name="database_name"
db_username="database_username"
db_password="database_password"
## 2: Path to your WordPress Upload and Theme directories. Replace /home/username/ with path to your home directory.
wp_upload_folder="/home/username/public_html/wp-content/themes"
wp_theme_folder="/home/username/public_html/wp-content/uploads"
## 3: Path to your backup folder. Replace /home/username/ with path to your home directory.
backup_folder_path="/home/username/wp_backup"
# backup MYSQL database, gzip it and send to backup folder.
mysqldump --opt -u$db_username -p$db_password $db_name | gzip > $backup_folder_path/$db_backup_name
# create a tarball of the wordpress files, gzip it and send to backup folder.
tar -czf $backup_folder_path/$wpfiles_backup_name $wp_upload_folder $wp_theme_folder
# delete all but 5 recent wordpress database back-ups (files having .sql.gz extension) in backup folder.
find $backup_folder_path -maxdepth 1 -name "*.sql.gz" -type f | xargs -x ls -t | awk 'NR>5' | xargs -L1 rm
# delete all but 5 recent wordpress files back-ups (files having .tar.gz extension) in backup folder.
find $backup_folder_path -maxdepth 1 -name "*.tar.gz" -type f | xargs -x ls -t | awk 'NR>5' | xargs -L1 rm
This script backs up wordpress database and then gzips it and saves it in the backup folder. It then makes a tarball of all the files in the wp-content uploads folder and the wp-content themes folder and then gzips it and saves it to the backup folder. (You should be able to open these files using an application like Winzip.)
The backups will follow this naming convention:
Database Backup: wp-db-backup-year-month-day.sql.gz eg: wp-db-backup-2015-04-12.sql.gz WordPress File Backup: wp-files-backup-year-month-day.tar.gz eg: wp-files-backup-2015-04-12.tar.gz
The script also ensures that there are no more than five recent copies of the backup by automatically deleting the older files. This way you can be sure that you do not run out of disk space because of too many backup files.
Step 2: Edit parts of the script that have two hash tags to them (##). #1 is the Mysql database name, username and password. You can get these details from the wp-config.php file of your wordpress installation. For #2 and #3, replace /home/username/ with path to your home directory.
Step 3: Save this file with the name backup and with a .sh extension so your filename looks like this: 'backup.sh'.
1.) Open your notepad. Paste the above code in it.
2.) Go to 'File > Save as..'.
3.) In 'Save as type' select 'All Files'.
4.) Now enter your filename as backup.sh and save the file.
If you have a program like Notepad++, you can choose, unix scrip file (.sh,.bsh) from the 'Save as type' section.
Step 4: Upload this .sh file into the backup folder you created before.
If you want, you can change the permissions of this file to 0600. To do this, right click on the file, select properties and uncheck read and write rights for group and others. This is for added security.
3: Adding the cron Job
Now we need to add a cron job to call this script at regular intervals. To create a cron job, do the following:
Step 1: Login to your Cpanel Account. If you don't know how, check this tutorial.
Step 2: Scroll down to the Advanced section and click on cron Jobs.
Step 3: From the Add a cron Job section, select Once Per Day from the Common Settings. And then add the following in the Command section:
/bin/sh /home/username/wp_backup/backup.sh
Step 4: Click on Add New cron Job.
Note: Make sure to replace /home/username/ with the path to your home directory.
Step 4: Downloading and Testing Backup Files
It is important that you download a fresh copy of your back up files from the backup directory at-least on a weekly basis. To do this, FTP to your server, go to the downloads folder and download a copy of the latest file.
Once downloaded to your computer, check if the theme and image files have been properly backed up by unzipping them. You can check your database back-up by loading it onto a test server or a local wamp server.
http://en.kioskea.net/faq/811-how-to-use-the-tar-command
http://stackoverflow.com/questions/1401482/yyyy-mm-dd-format-date-in-shell-script
http://stackoverflow.com/questions/25785/delete-all-but-the-most-recent-x-files-in-bash/
http://www.bloggingpro.com/archives/2009/12/21/automate-wordpress-database-and-files-backup/
Excellent article. Backup is an important thing for businesses. And automating this saves a lot of time. Thanks for explaining things. :)
This can be further improved by reading DB, User and Password from a local wp-config.php using the following commands.
WPDBNAME=`cat wp-config.php | grep DB_NAME | cut -d \' -f 4`
WPDBUSER=`cat wp-config.php | grep DB_USER | cut -d \' -f 4`
WPDBPASS=`cat wp-config.php | grep DB_PASSWORD | cut -d \' -f 4`
(courtesy: https://stackoverflow.com/questions/7586995/read-variables-from-wp-config-php)
Thank you so much for your script. It saved my ass.
Script works like a charm.
While running the script i got below warning,
~~~
[root@ip-172-31-41-237 wp_backup]# sh backup.sh
tar: Removing leading `/' from member names
rm: missing operand
Try 'rm --help' for more information.
rm: missing operand
Try 'rm --help' for more information.
~~~
Do you know how to avoid this?
I have same problem. Did you solve it?
Hi,
TY for your script.
I have to noticed you inverted paths (no caps)
wp_upload_folder="/home/username/public_html/wp-content/UPLOADS"
wp_theme_folder="/home/username/public_html/wp-content/THEMES"