~/blog/backup-database-mongodb-cron-shell-script
Published on

Automating MongoDB Database Backup Using Cron and Shell Script

book4 minutes read

Bash Shell Script

source

In this post, I want to write about how to automatically backup a database using Cron and Shell Script. I believe that database backup is very important, as I myself, being a server administrator, have experienced a security breach, and the last backup I had was very old and was done manually. Of course, that incident was quite an adrenaline rush, haha.

Okay... enough with the story... let's discuss what Cron is and what Shell Script is.

Cron is a default program available on Linux or Unix operating systems that is used to run tasks scheduled in the crontab (cron table).

Shell Script is a series of commands that will be executed by the shell. Wait... then what is Shell?
Shell is a program that acts as a bridge between the user and the operating system so they can communicate with each other. ~~I think that’s how it works.~~

Create Shell Script

First, let's create the shell script file

touch mongodb_backup.sh
nano mongodb_backup.sh

Here, I’m using someone else's script, which I’ve slightly modified to suit my server’s needs.

Here’s the script along with an explanation:

#!/bin/bash

######################################################################
##
##   MongoDB Database Backup Script
##   Written By: Rahul Kumar
##   URL: https://tecadmin.net/shell-script-backup-mongodb-database/
##   Updated on: June 20, 2020
##
######################################################################

set -e  
export PATH=/bin:/usr/bin:/usr/local/bin

TODAY=`date +"%d%b%Y"` # Get today’s date  
LAST_DAY=`date -d "-$(date +%d) days +1 month" +%d%b%Y` # Get the last day of the current month

DB_BACKUP_PATH='/home/user/backups/daily' # Path for daily backup directory  
DB_BACKUP_PATH_MONTHLY='/home/user/backups/monthly' # Path for monthly backup directory, leave empty if monthly backup is not needed

MONGO_HOST='localhost'  
MONGO_PORT='27017'

# If MongoDB is protected with a username and password,
# Set AUTH_ENABLED to 1
# and add the correct values for MONGO_USER and MONGO_PASSWD

AUTH_ENABLED=0 # Change to 1 if authentication is required  
MONGO_USER=''  
MONGO_PASSWD=''

# Set DATABASE_NAMES to "ALL" to backup all databases,
# or specify database names separated by spaces to backup
# only specific databases.

DATABASE_NAMES='db_name' # Value of the database name to be backed up

## Number of days to keep the local backup copy
BACKUP_RETAIN_DAYS=7 # Number of days to keep the backup stored locally

######################################################################
######################################################################

mkdir -p ${DB_BACKUP_PATH}/${TODAY} # Create a directory for today’s backup

AUTH_PARAM=""  
# If MongoDB requires user authentication
if [ ${AUTH_ENABLED} -eq 1 ]; then
  # Add username and password parameters
  AUTH_PARAM=" --username ${MONGO_USER} --password ${MONGO_PASSWD} "
fi

# If the value of DATABASE_NAMES is ALL
if [ ${DATABASE_NAMES} = "ALL" ]; then
  # Backup all databases
  echo "You have chosen to backup all databases"
  mongodump --host ${MONGO_HOST} --port ${MONGO_PORT} ${AUTH_PARAM} --out ${DB_BACKUP_PATH}/${TODAY}/
else
  # If not, backup according to the list
  echo "Running backup for selected databases"
  for DB_NAME in ${DATABASE_NAMES}
  do
  mongodump --host ${MONGO_HOST} --port ${MONGO_PORT} --db ${DB_NAME} ${AUTH_PARAM} --out ${DB_BACKUP_PATH}/${TODAY}/
  done
fi

# If today’s date is the same as the last day of the month
# and DB_BACKUP_PATH_MONTHLY is not empty
if [ "$TODAY" == "$LAST_DAY" ] && [ ! -z ${DB_BACKUP_PATH_MONTHLY} ]; then
  # Create a monthly directory
  mkdir -p ${DB_BACKUP_PATH_MONTHLY}
  # Copy today’s backup to the monthly directory
  cp -ar ${DB_BACKUP_PATH}/${TODAY} ${DB_BACKUP_PATH_MONTHLY}/${LAST_DAY}
fi

######## Remove backups older than {BACKUP_RETAIN_DAYS} days  ########

# Get today’s date minus the value of BACKUP_RETAIN_DAYS
DBDELDATE=`date +"%d%b%Y" --date="${BACKUP_RETAIN_DAYS} days ago"`  
# If DB_BACKUP_PATH is not empty
if [ ! -z ${DB_BACKUP_PATH} ]; then
  cd ${DB_BACKUP_PATH}
  # If DBDELDATE is not empty
  # and DBDELDATE is a directory
  if [ ! -z ${DBDELDATE} ] && [ -d ${DBDELDATE} ]; then
    # Delete the backup directory
    rm -rf ${DBDELDATE}
  fi
fi

######################### End of script ##############################

From the script above, we’ve created a shell script that can be executed daily to perform daily and monthly database backups by creating directories according to the date the script is executed and automatically deleting old directories based on the backup retention days we’ve set in the script.

Next, we need to set the file’s permissions so it can be executed:

chmod +x mongodb_backup.sh

Create Crontab

After that, we create a crontab to execute the script by running the command:

crontab -e

Then add the following script:

0 2 * * * /home/user/backups/mongodb_backup.sh >> /home/user/backups/mongodb_backup.log 2>&1

The script above means that we are adding a task for cron to run the mongodb_backup.sh script every day at 2 AM.

Additional

If you encounter the error ... mongodump error Unrecognized field 'snapshot'. while executing the script, add the --forceTableScan option to the mongodump command in the script:

mongodump --forceTableScan --host ${MONGO_HOST} --port ${MONGO_PORT} ${AUTH_PARAM} --out ${DB_BACKUP_PATH}/${TODAY}/

This usually happens when the mongodump tool version differs from the target database version.

Oh yeah, to restore the database, you can use the following command:

mongorestore -d db_name db_name_directory

You can download the original script from GitHub.

That’s all, see ya~