#!/bin/bash ## Remote Server Backup Script ## Author: Ze'ev Schurmann ## Reddit: u/thisiszeev ## License: GPL-3.0 or later ## This script can only backup one server. So you need a seperate folder for each server. Put this file in each folder and apply ## the relative settings to each server. If you want to get Telegram notifications then check the API documents on the Telegram ## Website. Use a cron job to schedule each run. If you have more than one server, then stagger them. If you are backing up to a ## local machine that is not on redundant power, schedule each backup to run more than once a day, just incase of a power failure ## during a backup. The script will know if the last attempt was successful or not. ## Dependancies: ## rsync, ssh, tar, gzip, wget ## make sure you have key pair authentication setup for ssh. Rsync must be installed on both the remote server and the local machine. ## Use the SQLDumps script to export all MySQL and MariaDB databases on the server. Ensure the SQLDump runs long before this script ## runs to ensure that all databases are completely dumped. ## Example crontab entries (exclude the ##) ## 30 2 * * * root cd /media/backupdrive/server1 && bash backup.sh ## 30 5 * * * root cd /media/backupdrive/server2 && bash backup.sh ## 30 8 * * * root cd /media/backupdrive/server1 && bash backup.sh ## 05 11 * * * root cd /media/backupdrive/server2 && bash backup.sh ## 30 14 * * * root cd /media/backupdrive/server1 && bash backup.sh ## 30 17 * * * root cd /media/backupdrive/server2 && bash backup.sh ## 30 20 * * * root cd /media/backupdrive/server1 && bash backup.sh ## 30 23 * * * root cd /media/backupdrive/server2 && bash backup.sh ## Please consider making me small donation. Even though my scripts are open source and free to use, I still need to eat. And the ## occasional bottle of wine also goes down well. ## $5 buys me a cup of coffee ## $10 buys me a nice burger ## $20 buys me a bottle of wine ## Anything above that will be awesome as well. ## You can send me a donation via Paypal https://www.paypal.com/paypalme/thisiszeev ## Drop me a message on Reddit if you do make a donation. ## Support is only offered freely to those who donate $20 or more. ## Your donation contributes to further development. ## If you need a custom script, contact me on Reddit for pricing. ## Telegram API and Channel Settings ## Set usetelegram to true to get sent Telegram notifications. The Telegram API documentation covers how to obtain a bot key and how ## to assign the bot to a channel. Channels are used as it means notifications can be sent to more than one person if they are all ## in the same channel. usetelegram=false tgapi="placekeyhere" tgch="placechannelhere" ## Backup Settings ## patharray contains a list of the folders you need to backup. patharray=("/var/log" "/var/www" "/var/sqldumps" "/var/mail" "/var/vmail") ## serverlogin is your SSH login serverlogin="root@server1.example.com" servername="Server1" ## keepday is the day of the week you want for you weekly backups. keepday="sunday" function ShiftMonths { echo "Shifting months and copying $dayname.tar.gz to month1.tar.gz" >> backup.log rm month6.tar.gz mv month5.tar.gz month6.tar.gz mv month4.tar.gz month5.tar.gz mv month3.tar.gz month4.tar.gz mv month2.tar.gz month3.tar.gz mv month1.tar.gz month2.tar.gz cp $dayname.tar.gz month1.tar.gz } function ShiftWeeks { echo "Shifting weeks and copying sunday.tar.gz to week1.tar.gz" >> backup.log rm week5.tar.gz mv week4.tar.gz week5.tar.gz mv week3.tar.gz week4.tar.gz mv week2.tar.gz week3.tar.gz mv week1.tar.gz week2.tar.gz mv sunday.tar.gz week1.tar.gz ln -s week1.tar.gz sunday.tar.gz } function PrepareFiles { if [ ! -f sunday.tar.gz ]; then touch sunday.tar.gz echo "Init Sun" fi if [ ! -f monday.tar.gz ]; then touch monday.tar.gz echo "Init Mon" fi if [ ! -f tuesday.tar.gz ]; then touch tuesday.tar.gz echo "Init Tue" fi if [ ! -f wednesday.tar.gz ]; then touch wednesday.tar.gz echo "Init Wed" fi if [ ! -f thursday.tar.gz ]; then touch thursday.tar.gz echo "Init Thu" fi if [ ! -f friday.tar.gz ]; then touch friday.tar.gz echo "Init Fri" fi if [ ! -f saturday.tar.gz ]; then touch saturday.tar.gz echo "Init Sat" fi if [ ! -f month1.tar.gz ]; then touch month1.tar.gz echo "Init M1" fi if [ ! -f month2.tar.gz ]; then touch month2.tar.gz echo "Init M2" fi if [ ! -f month3.tar.gz ]; then touch month3.tar.gz echo "Init M3" fi if [ ! -f month4.tar.gz ]; then touch month4.tar.gz echo "Init M4" fi if [ ! -f month5.tar.gz ]; then touch month5.tar.gz echo "Init M5" fi if [ ! -f month6.tar.gz ]; then touch month6.tar.gz echo "Init M6" fi if [ ! -f week1.tar.gz ]; then touch week1.tar.gz echo "Init W1" fi if [ ! -f week2.tar.gz ]; then touch week2.tar.gz echo "Init W2" fi if [ ! -f week3.tar.gz ]; then touch week3.tar.gz echo "Init W3" fi if [ ! -f week4.tar.gz ]; then touch week4.tar.gz echo "Init W4" fi if [ ! -f week5.tar.gz ]; then touch week5.tar.gz echo "Init W5" fi for ((n=0; n<${#patharray[@]}; n++)) do mkdir -p "./backup${patharray[$n]}" done } dom=$( date +%d ) if [ -f backup.log ]; then check=$( tail -1 backup.log ) if [[ -z $check ]]; then sleep 0.1s elif [[ $check == "T_$dom" ]]; then echo "Backup already completed successfully today!" exit fi fi firstruncheck=$( ls -1 | grep "tar.gz") if [[ -z $firstruncheck ]]; then PrepareFiles fi SECONDS=0 if [[ $usetelegram == true ]]; then string="Starting backup of $servername." wget -qO- "https://api.telegram.org/bot$tgapi/sendMessage?chat_id=$tgch&text=$string" &> /dev/null fi dow=$( date +%u ) if [ $dow == "1" ] then dayname="monday" elif [ $dow == "2" ] then dayname="tuesday" elif [ $dow == "3" ] then dayname="wednesday" elif [ $dow == "4" ] then dayname="thursday" elif [ $dow == "5" ] then dayname="friday" elif [ $dow == "6" ] then dayname="saturday" else dayname="sunday" fi echo "Start: $( date )" >> backup.log for ((n=0; n<${#patharray[@]}; n++)); do if [ -z $1 ]; then rsync -avhPz --delete "$serverlogin:${patharray[$n]}/" "./backup${patharray[$n]}/" elif [ $1 == "quiet" ]; then rsync -avhqz --delete "$serverlogin:${patharray[$n]}/" "./backup${patharray[$n]}/" else rsync -avhPz --delete "$serverlogin:${patharray[$n]}/" "./backup${patharray[$n]}/" fi done echo "Rsync complete: $( date )" >> backup.log echo "Day of Week = $dow | Day of Month = $dom" >> backup.log echo "Generating $dayname.tar.gz" >> backup.log rm $dayname.tar.gz if [ -z $1 ]; then tar -czvf $dayname.tar.gz ./backup elif [ $1 == "quiet" ]; then tar -czf $dayname.tar.gz ./backup else tar -czvf $dayname.tar.gz ./backup fi if [ $dom == "1" ]; then ShiftMonths elif [ $dom == "01" ]; then ShiftMonths fi if [ $dayname == $keepday ] then ShiftWeeks fi temp=( $( du -b ./backup/ | tail -1 ) ) size1=${temp[0]} size2=$( stat -c%s $dayname.tar.gz ) size1si=$( numfmt --to=iec-i --suffix=B --format="%9.2f" $size1 ) size2si=$( numfmt --to=iec-i --suffix=B --format="%9.2f" $size2 ) size2percent=$(( size2 * 100 )) ratio=$( expr $size2percent / $size1 ) duration=$SECONDS echo "Finished: $( date )" >> backup.log echo "Data size: $size1si | Archive size: $size2si | Ratio: $ratio%" >> backup.log echo "T_$dom" >> backup.log tail -n 5000 backup.log > temp.log rm backup.log mv temp.log backup.log if [[ $usetelegram == true ]]; then echo "Backup of $servername Complete: $( date )" >> tg.txt echo "Data Size: $size1si" >> tg.txt echo "Archive Size: $size2si" >> tg.txt echo "Ratio: $ratio%" >> tg.txt echo "Duration: $( TZ=UTC0 printf '%(%H:%M:%S)T\n' $duration )" >> tg.txt string=$( cat tg.txt ) wget -qO- "https://api.telegram.org/bot$tgapi/sendMessage?chat_id=$tgch&text=$string" &> /dev/null rm tg.txt fi