Jump directly to main content

Automating Backups with Cronjobs



Backups are wonderful things that save hours upon hours of work, and stress, so long as they're actually made in the first place!

Automatically taking backups allows for peace of mind that your work won't be lost forever whilst you go about your normal workflow..

Create a backup script

You can just call rsync, etc. in cron, but I recommend making a backup script (or a few) for each specific type of backup you want to make.

Create the file where-ever you want to keep them, for the sake of this, it'll be a scripts directory in your home directory

vim ~/scripts/backup_script.sh

And add whatever your backup scripts wants to do. If you've no idea, check out my rsync, and rdiff articles first.

rdiff-backup $DIRECTORY_TO_BACKUP $DIRECTORY_TO_BACKUP_TO
rdiff-backup --force --remove-older-than 2W $DIRECTORY_TO_BACKUP_TO

The above example will backup a directory, and remove any changes from 2 weeks ago.

Now make the script executable

chmod +x ~/scripts/backup_script.sh

Add a cronjob

Now for the automation part. Using cron we can set this script to run at many time variations. I recommend crontab guru to learn more about the expressions used for cron.

Edit the cron table (crontab)

crontab -e

And add the following

* */2 * * * /home/$USERNAME/scripts/backup_script.sh

This will run the backup script every 2 hours, every day

An advanced backup script

An advantage of using a script for backups, is that it allows for more intricate functionality, you may not need to use this functionality, but it's greatly useful.

The script below is something I wrote to backup my home directories for each of my servers. It's used to make hourly backups, and send these backups to a remote server daily at midnight.

#!/bin/bash

# Set locations to backup/backup to from the flags
while getopts s:d:b:r:R:n: flag
do
        case "${flag}" in
            d) DATA=${OPTARG};;
            b) BACKUPDIR=${OPTARG};;
            r) REMOTE=${OPTARG};;
            R) REMOTEBACKUP=${OPTARG};;
            n) NOW=${OPTARG};;
        esac
done

# If the backup directory doesn't exist, make it
mkdir -p $BACKUPDIR

# Incremental backup of the directory locally
rdiff-backup $DATA $BACKUPDIR
# Don't keep changes from over 1W ago
rdiff-backup --force --remove-older-than 1W $BACKUPDIR

# Backup to remote
# Get the hour/minute time
TIME=$(date +%H%M)

# If it's a midnight backup, or a manual backup with -n 1 flag set
if [ "$TIME" = 0000 ] || [ "$NOW" = 1 ]
then
        # Create the remote directory for backup if it doesn't exist
        ssh $REMOTE mkdir -p $REMOTEBACKUP

        # Copy the backup to the remote location
	# -e ssh makes it secure
        rsync -azh -e ssh \
                --delete \
                $BACKUPDIR \
                $REMOTE:$REMOTEBACKUP
fi

Which is called in the crontab like so

# Hourly rdiff-backup of $DIRECTORY_TO_BACKUP
0 */1 * * * $SCRIPT_LOCATION -d $DIRECTORY_TO_BACKUP -b $LOCATION_TO_SAVE_BACKUP -r $EXTERNAL_SERVER_SSH -R $EXTERNAL_SERVER_BACKUP_LOCATION

This script can easily be used for many different directories, on each server without needing to change the script itself. All that's needed is to change the cronjob, and/or add another cronjob changing the values it takes.

One off scheduling

If you only want something to happen once at a specific date/time, you should look into using at, for one off scheduling rather than cron.