Simple Website Backup shell script

A simple shell script to backup the files of your websites along with the databases

Sat 04 Jan 2020
  
er

In this article I would like to share with you a rather simple shell script I made quite some time ago when I was managing VPSs that were serving websites. The VPSs were using CentminMod, which is a super useful LEMP stack auto installer. Using CentminMod you can create several websites within the same VPS and it handles automatically many tedious tasks.

In order to automatically get backups of the websites' files along with the databases I made this script which in combination with another one it would ftp these files safely to another location.


A list of features this script includes are given below
:

  1. Verbose details upon execution.
  2. Notifications through Pushover upon failure or success.
  3. Email the results.
  4. Delete backups older than 5 days
  5. Skips schema databases and all databases with underscore.
  6. Reports size of each database.


So lets see the script itself.

#!/bin/bash

datenow=`date +"%Y%m%d"`
#user used for databases backup
USER=""
#password for the user above
PASSWORD=""
#all files backup path
path="/root/sitesBackups/"
#pushover details
TOKEN=""
USERID=""
#Email to send notifications to
MAIL=""
#the path where your sites files are
sitespath="/home/nginx/domains/"
STATUS="/root/sitesBackups/statusfile.$datenow"
siteslist=$(ls $sitespath)



# If the directory does not exist, make it please
if [ ! -d $path ]; then
  mkdir -p $path
else
 :
fi



# SITES FILES BACKUP
printf "these sites will be backed up\n $siteslist\n"
cd $path
var1=0
for site in $siteslist; do
tar -cf $site$datenow.tar $sitespath$site
gzip $site$datenow.tar
gunzip -c $site$datenow.tar.gz | tar t > /dev/null
successcode=$?
		if [ $successcode -ne 0 ]; then
		curl -s \
		-F "token=$TOKEN" \
        -F "user=$USERID" \
        -F "message=$site ERROR BACKING UP === errorcode = $successcode   " \
        -F "priority=1"\
        https://api.pushover.net/1/messages.json	
		printf "\n\n$site ERROR BACKING UP === errorcode = $successcode \n\n" >> $STATUS
		((var1++))
		else
		printf "\n$site Backed up with EXITCODE [ $successcode ]\n" >> $STATUS
		fi
done



# DATABASES BACKUP
DBS="$(mysql -u$USER -p$PASSWORD -Bse 'show databases')"
echo "$DBS"

errorcounter=0 #innitializing a variable to count errors in mysqldump

#if your db starts with an _ then ignore it this way you can create dbs with _ if you want them ignored
#need to add a list of databases so you can add a database you need to be ignored
for db in $DBS; do
    if [[ "$db" != "information_schema" ]] && [[ "$db" != _* ]] && [[ "$db" != "performance_schema" ]] ; then
        printf "Dumping database: $db\n"
		        mysqldump --force --opt --user=$USER --password=$PASSWORD --databases $db > $path/`date +%Y%m%d`.$db.sql
				exitcode=$?
        gzip $path/$datenow.$db.sql
		FILESIZE=$(stat -c%s "$path/$datenow.$db.sql.gz")
		printf "$db Backed up with EXITCODE [ $exitcode ] and with size $FILESIZE bytes\n";
		
		#create an if to notify us in case of bad mysqldump
		if [ $exitcode -ne 0 ]; then
		curl -s \
		-F "token=$TOKEN" \
        -F "user=$USERID" \
        -F "message=$db ERROR BACKING UP === errorcode = $exitcode   " \
        -F "priority=1"\
        https://api.pushover.net/1/messages.json	
		printf "\n\n$db ERROR BACKING UP === errorcode = $exitcode \n\n" >> $STATUS
		((errorcounter++))
		else
		printf "\n$db Backed up with EXITCODE [ $exitcode ] and with size $FILESIZE bytes\n" >> $STATUS
		fi
		
	fi
done


# To remove old database backups
if [ $errorcounter -ne 0 ] || [ $var1 -ne 0 ]; then
	printf "Not deleting anything due to errors in mysqldump\n" >> $STATUS
else
	find $path -mtime +5 -exec rm {} \;
	printf "\nFiles older than 5 days have been deleted\n" >> $STATUS
fi


# Send a Pushover Notification
        curl -s \
        -F "token=$TOKEN" \
        -F "user=$USERID" \
        -F "message=server is $(hostname) $(cat $STATUS)" \
        -F "priority=0"\
        https://api.pushover.net/1/messages.json
		
# Send by email
printf "Server hostname is $(hostname)\n$(cat $STATUS)" | mail -s "$(hostname) Backup Results" $MAIL



Lets explain a bit the code above. Lines 5-14 contain variables that are required to be filled by the user.

  • USER and PASSWORD need to contain the credentials of a user who has access to the database so it can take a backup using mysqldump.
  • path is where you would like the backups to be stored.
  • TOKEN and USERID are related to the Pushover service, if you would like to receive notification using it.
  • MAIL is the email where you want the results to be mailed to.



  • Lines 16-18 have three variables that are the sitespath which is the location where the directories of the sites are located, siteslist the list of the sites in the sitespath and STATUS which is a file where the script saves the results from the backup of the directories and the databases. The datenow is only the current date so we could differentiate between executions.
  • Lines 22-27, it checks if the path where we will store the backups exists and if it does not exist it creates the directory.
  • Lines 32-52, we make the backups of the directories and notify through Pushover if we have a failure.
  • Lines 56-88, the dump of the databases happens, where we are notified through Pushover if something goes wrong and we also get printed details of the size of each database.
  • Lines 91-97, we delete already existing backups that are older than 5 days.
  • Lines 100-109, we report through Pushover and Email the final Results that are stored in the STATUS file.


TIP

You can add this script in a cronjob so it can be executed automatically



In order to do this you need to run crontab -e and add a line similar to this 0 0 */2 * * /root/tools/dbbackup.sh 2>/dev/null, which will execute the script every two days. Dont forget to make the script executable!


Disclaimer: I have not tested this script recently but I believe it would work. Please make sure you know what you are doing as it will delete files older than five days when it is executed!