Contents

Auto Generating Backup Files for your Linux Server

source image: pexel.com

When doing computer work, clicking “save” is necessary to either literally or not literally save your job. This content is helpful when you are working on the Linux Operating System (OS), especially running a server. Automatically backing up your server can cost you money on a monthly basis and, of course, can save your business.

Just imagine how much of your time and effort goes to waste when you forget or have the tardiness to just press ctrl + s on your office application. Without further ado, let’s get started.

Prerequisite

Things you need before you proceed:

  • Computer running Linux Operating System
  • SSH to access Linux OS Server (situational)
  • Free storage enough to save your work
  • nano, vim, or your favorite text editor
  • Cronjob crontab -e

This is a bash script dependencies are to follow:

  • tar
  • tee
  • head
  • xargs
  • gzip

If some bash commands are not natively installed, just i.e. sudo apt install gzip in the terminal.

How Back-up Script works?

This automation is using a crontab. Let’s say you have two folders in the tree (for simplicity).

/blog/posts/automatically-backup-files-your-server-files/backup-folder.png

– OR –

Visually..

  • Backup -The folder where all your backups go
  • Documents – The folder where all your important files are saved i.e. web files, office files.
  • backup-script.sh – an executable bash file

Basically, this script creates an archive file (named filename.tar.gz) of Documents folder and automatically saves it to Backup folder.

The Bash Code

In your terminal command, just copy and paste the single command line below:

Go to your parent folder like Public and create a file using your favorite editor.

nano backup-script.sh

Copy and Paste below:

#!/bin/bash
##
# ./backup-files SOURCE DESTINATION
# (2) PARAMETERS required, destination where to save
# backup files and target files to backup
# .log File is in destination folder
#
# Pre-requisite: tar, tee, head, xargs, gzip
#
# Make it executable
# chmod u+x ./backup-files.sh
#
##
START=$(date +%s)
LOGS=$(date '+%m-%d-%Y %H:%M:%S')
if [ -z "$1" ] || [ -z "$2" ]; then
    LOGS+=" - ERROR: (2) PARAMS required"
        echo $LOGS
        echo "usage:"
        echo "./backup-files.sh SOURCE_FOLDER DESTINATION_FOLDER"
        echo "SOURCE_FOLDER - file source to be added in the archive"
        echo "DESTINATION_FOLDER - file destination to where the archive.tar.gz is saved"
        echo "e.g."
        echo "./backup-files.sh /home/username/public_hmtl /home/username/backup"
        exit 255;
fi

#PARAMS
DEBUG=false #Bolean
KEEP_FILES=5 #Only keep 5 recent files; 0 to disable
SOURCE_FOLDER=$1 # SOURCE_FOLDER="backup-source backup-another-source" #the folder that contains the files that we want to backup
BACKUP_FOLDER=$2
CWD=$(pwd) # assigning Current Working Directory (CWD)
#Database Exports
# Note: No whitespace in the -p Flag
# Warining: Careful of hard coded credentials
#mysqldump -u username -p'SecurePassword' DatabaseName | gzip > /home/username/www/public/backup/DatabaseName_`date +\%m-\%d-\%Y_\%H:\%M`.sql.gz

# Preinstalls --> For testing purpose only; delete this
if [[ "${DEBUG}" == "true" ]]; then
    echo "---START Preinstall----"
    mkdir -p $SOURCE_FOLDER && cd $SOURCE_FOLDER #
    SOURCE_FOLDER=$(pwd) # Re-assigning to absolute path
    mkdir -p new-folder
    echo "This is file 1" | tee -a ./file1.txt >/dev/null 2>&1
    echo "<h2>This is file 2</h2>" | tee -a ./file2.html >/dev/null 2>&1
    echo "<h3>This is file 3</h3>" | tee -a ./new-folder/file3.htm >/dev/null 2>&1
    pwd && ls
    echo -e "---END Preinstall---- \r\n"
fi
## End of preinstall --> delete until here.

# Check if Source Folder is not empty
if [ ! -d $SOURCE_FOLDER ] || [ -z "$(ls -A $SOURCE_FOLDER)" ]; then
    echo "error: SOURCE FOLDER is empty"
    exit 255;
fi

# The following is path correction for supposedly accuracy
cd $SOURCE_FOLDER && SOURCE_FOLDER=$(pwd) # Re-assigning to absolute path
cd $CWD && mkdir -p $BACKUP_FOLDER # Create backup folder if not available
cd $BACKUP_FOLDER && BACKUP_FOLDER=$(pwd) # Re-assigning to absolute path

FOLDERNAME="" # we don't know yet
TRIMPATH="[^\/]+$" # capture the backup folder name only
# Trim function
if [[ $BACKUP_FOLDER =~ $TRIMPATH ]]; then FOLDERNAME=${BASH_REMATCH[0]}
fi

BACKUPDATE=`date +%b-%d-%Y` #get the current date #replace this path
BACKUP_FILE=$BACKUP_FOLDER/backup-$BACKUPDATE.tar.gz

# Remove older backups first
# Check if file if exists
if [ $KEEP_FILES != 0 ] && [ -d $BACKUP_FOLDER ] && [ -n "$(ls -A $BACKUP_FOLDER)" ]; then
    # Only keep 5 recent backup files
    LOGS+="$(ls -tr $BACKUP_FOLDER/backup-*.tar.gz | head -n -$KEEP_FILES | xargs --no-run-if-empty rm)"
fi

# Avoid duplicate backup if exist
[ -f "$BACKUP_FILE" ] && rm $BACKUP_FILE

cd $SOURCE_FOLDER # Change Directory to avoid "tar: Removing leading `/' from member names" error
LOGS+="- Backup is running.. "
if [[ "${DEBUG}" == "true" ]]; then
    LOGS+="$(tar --exclude=*/$FOLDERNAME -zvcf $BACKUP_FILE .)" #create the backup, just add -v flag for verbose
else
    LOGS+="$(tar --exclude=*/$FOLDERNAME -zcf $BACKUP_FILE .)" # non-verbose
fi

END=$(date +%s)
DIFF=$(( $END - $START ))
LOGS+="It took $DIFF second to backups."

# Printing logs
echo -e $LOGS | tee -a $BACKUP_FOLDER/backup0.log >/dev/null 2>&1
echo $LOGS

# Debug results
if [[ "${DEBUG}" == "true" ]]; then
    echo "---Start Debug Extract---"
    cd $BACKUP_FOLDER && pwd && ls -lah
    tar -xvf backup-$BACKUPDATE.tar.gz >/dev/null 2>&1
    echo -e "\r-- Files from Extracted from backup-$BACKUPDATE.tar.gz --"
    pwd && ls -lah
    echo -e "\r-- Log File --"
    cat backup0.log
    echo "---End Debug Extract---"
fi
exit 0

Note: To test the code above, just run this code on jdoodle.com but set DEBUG=true

Command Line Arguments:

./backup-script.sh home/username/backup /home/username/public_hmtl

Important: DEBUG=true

This could be boring, but this is an awesome script (quote and quote) 😀

Executing the Backup Script

Make the file executable by a current user (your self) running terminal command below:

chmod u+x ./backup-script.sh

Automation

Make the backup script executable for the current user (as yourself) by running the terminal command below:

crontab -e

Choose your favorite code editor, I suggest choosing nano editor for simplicity.

Add the cron job code at the very last line.

0 1 * * 0 ~/public/backup-script.sh ~/public/Documents ~/public/Backup >> ~/public/cron.all.log 2>&1

This will run every “At 01:00 on Sunday.” To play around with the cron scheduler, try and test with crontab.guru is highly recommended.

0 1 * * 0 – weekly basis

0 8 * * * – daily basis at 08:00am

Manually (Situational)

You can also manually use this script by running..

./backup-script.sh ~/public/Documents ~/public/Backup

Recommendations

Generating database backup files must come first before invoking this backup script. In the next topic, let’s talk about “How to automatically backup your SQL database”.

Disclaimer

This script is well tested in the production environment or real-world scenario and carefully written to prevent any unnecessary bugs or outcomes. However, I am not liable for any issues that this script may cause you. But feel free to drop your comments below if you have questions, suggestions, or recommendations. I would appreciate it. Thank you!