Skip to content

Instantly share code, notes, and snippets.

@pirogoeth
Created July 15, 2014 15:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pirogoeth/a06922ebb6d84340bfa1 to your computer and use it in GitHub Desktop.
Save pirogoeth/a06922ebb6d84340bfa1 to your computer and use it in GitHub Desktop.
super fabulous backup script
#!/usr/bin/env bash
if [ "${BS_DEBUG}" == "YES" ] ; then
set -x
fi
# this is a configurable backup script that should run on a cron job.
# declares the arrays we'll be using, don't change these
declare -a backup_folders
declare -a backup_folder_sizes
# configuration
backup_device="/dev/ad8s1d"
backup_device_mountpath="/var/backups" # NO TRAILING SLASH
backup_target_folder="/jenova/"
backup_folders=( "/etc" "/usr/home" "/usr/local/etc" "/var/www" )
backup_folder_sizes=( )
backup_name="`date +%Y-%m-%d`_`hostname | tr . ' ' | awk '{print $1}'`_backup.tar"
backup_logdir="/tmp" # NO TRAILING SLASH
backup_logfile_name="`date +%Y-%m-%d`_`hostname | tr . ' ' | awk '{print $1}'`_backup.log"
# optional config options
tar_path="`which tar`" # default: `which tar`
# bash colors
_green='\033[1;32m'
_yellow='\033[1;33m'
_red='\033[0;31m'
_white='\033[0m'
# path to backup file
backup_file="${backup_device_mountpath}${backup_target_folder}${backup_name}"
# post-op function values
post_umount="NO"
# traps
trap displayBackupSize EXIT
trap clearColours EXIT
trap destroyBackup INT
# functions
function validateBackupLocation() {
device_actual_mountpath="`df -h | grep "${backup_device}" | awk '{print $6}'`"
if [ -z "${device_actual_mountpath}" ] ; then
echo -e "Uh-oh, it appears that ${_yellow}${backup_device}${_white} is not mounted!"
if [ $EUID == 0 ] ; then
echo -e "${_yellow}${backup_device}${_white} is being mounted at ${_green}${backup_device_mountpath}${_white}."
mount -o rw ${backup_device} ${backup_device_mountpath}
if [ $? != 0 ] ; then
echo -e "${_red}There was an error while mounting ${_yellow}${backup_device}${_red}!"
exit 1
fi
echo -e "${_yellow}${backup_device}${_white} will be unmounted from ${_yellow}${backup_device_mountpath}${_white} after the operation finishes."
post_umount="YES"
else
echo -e "${_yellow}This script must be run as root to mount ${_green}${backup_device}${_yellow}."
exit 1
fi
fi
device_actual_mountpath="`df -h | grep "${backup_device}" | awk '{print $6}'`"
if [ "${backup_device_mountpath}" != "${device_actual_mountpath}" ] ; then
if [ "${device_actual_mountpath}" == "" || "${device_actual_mountpath}" == " " ] ; then
echo -e "Uh-oh, it appears that ${_yellow}${backup_device}${_white} is still not mounted!"
echo -e "${_red}There was an error while mounting ${_yellow}${backup_device}${_red}!"
exit 1
fi
echo -e "Uh-oh, it appears that ${_yellow}${backup_device}${_white} is mounted at ${_red}${device_actual_mountpath}${_white}, not ${_green}${backup_device_mountpath}${_white}."
echo -e "Ok to adjust my configured path?"
read -p "[Y/n]: " continue
if [[ "${continue}" == "Y" || "${continue}" == "y" ]] ; then
backup_device_mountpath=${device_actual_mountpath}
else
exit 0
fi
fi
echo -e "${_green}Your backup path appears ok, continuing.."
}
function getFolderSizes() {
echo -e "${_yellow}Calculating backup sizes...${_white}"
for (( i=0; $i < ${#backup_folders[@]}; i++ )) ; do
folder_size="`du -mhd 0 -B 1M ${backup_folders[${i}]} | awk '{print $1}'`"
backup_folder_sizes[${i}]=`echo ${folder_size}`
echo -e "${_white} - ${backup_folders[${i}]} ${_red}=> ${_yellow}${folder_size}${_white}"
done
}
function createBackupArchive() {
if test -e ${backup_file} ; then
echo -e "${_yellow}There is already a backup for today! Aborting!"
exit 1
fi
${tar_path} -cf ${backup_file} /dev/null 2>/dev/null
if [ $? != 0 ] ; then
echo -e "${_red}There was an error while creating the backup archive! Aborting!"
exit 1
fi
}
function storeFoldersToArchive() {
if test ! -e ${backup_file} ; then
echo -e "${_yellow}Your backup file does not exist! Aborting!"
exit 1
fi
for (( i=0; $i < ${#backup_folders[@]}; i++ )) ; do
current_folder=${backup_folders[${i}]}
echo -e "Backing up ${_green}${current_folder}${_white} [ Approx. ${_yellow}${backup_folder_sizes[${i}]}${_white} ]..."
${tar_path} -uP --exclude="${backup_device_mountpath}/*" -f ${backup_file} ${current_folder} 2>&1 1>${backup_logdir}/${backup_logfile_name}
if [ $? != 0 ] ; then
echo -e "${_red}There was an error while compressing ${_yellow}${current_folder}${_white}! Aborting!"
exit 1
fi
done
}
function compressArchive() {
if test ! -e ${backup_file} ; then
echo -e "${_yellow}Your backup file does not exist! Aborting!"
exit 1
fi
backupfile_size=`du -mhd 0 -B 1M ${backup_file} | awk '{print $1}'`
echo -e "Compressing ${_green}${backup_file} [ Approx. ${_yellow}${backupfile_size}${_white} ].."
gzip -9v ${backup_file}
if [ $? != 0 ] ; then
echo -e "${_red}There was an error while compressing the backup archive! Aborting!${_white}"
exit 1
fi
backup_file="${backup_file}.gz"
}
function runPostActions() {
if [ "${post_umount}" == "YES" ] ; then
umount ${backup_device}
echo -e "Unmounted ${_green}${backup_device}${_white}!"
fi
}
function displayBackupSize() {
if [ -e ${backup_file} ] ; then
echo -e "${_yellow}Calculating total backup size..."
backup_file_du="`du -mhd 0 -B 1M ${backup_file}`"
backup_file_size="`echo ${backup_file_du} | awk '{print $1}'`"
echo -e "${_green}Backup archive is approximately ${backup_file_size}."
fi
}
function clearColours() {
echo -e "${_white}"
tput sgr0
}
function destroyBackup() {
echo -e "${_red}Received SIGINT, shutting down.."
if [ -e ${backup_file} ] ; then
rm -v ${backup_file}
echo -e "${_red}Partial backup removed, exiting."
fi
clearColours
exit 1
}
# procedure
validateBackupLocation
getFolderSizes
createBackupArchive
storeFoldersToArchive
compressArchive
runPostActions
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment