This is my first attempt at scripting with bash. I am running Ubuntu server, so I don't get to use all the gui back ups out there. Besides, tar works fine for personal use. Please let me know of any improvements and why.
#!/bin/bash
# PURPOSE:
# TO BACK UP ALL FILES AND FOLDERS FROM A GIVEN DIRECTORY
# Directory to back up is set with the constant BACK_UP_LOCATION
# Directory to save the back up to is /IT/backup/ and is set with the constant BACK_UP_DIR
# Directory to save the log files to is /IT/backup/log/ and is set by changing the tail end of the constant BACK_UP_LOG_DIR
# Obviously additional directories can be added to the back up by adding additional constants and incorporating that tar command(s) to go with them
# Written by Rowland Holden
# This script could have used the find command to delete the old files
# but that wouldn't have allowed for the logging of each deleted file so
# I chose to do it the long way to get the logging I wanted
# File Info: tar-share-backup @ cron.daily
# Set constants
NOW=$(date +%m-%d-%Y)
BACK_UP_DIR="IT/backup/"
BACK_UP_PATH="${BACK_UP_DIR}ShareBackup${NOW}"
BACK_UP_LOG_DIR="${BACK_UP_DIR}log/"
BACK_UP_LOG_PATH="${BACK_UP_LOG_DIR}ShareBackupLog${NOW}"
BACK_UP_LOCATION="srv/share/"
cd /
# check if script is already running
write_pid_running_error () {
local errorText="${0} is already running: canceling backup operation"
if [[ -f "${BACK_UP_LOG_PATH}" ]]; then
echo "" >> "${BACK_UP_LOG_PATH}"
echo "${errorText}" >> "${BACK_UP_LOG_PATH}"
else
echo "${errorText}" > "${BACK_UP_LOG_PATH}"
fi
}
for pid in $(pidof -x `basename $0`); do
if [[ $pid != $$ ]]; then
write_pid_running_error
exit 1
fi
done
# Check to see if the back up file already exists and write an error in the log if it does
# write error to log file if back up file exists
write_file_exists_error () {
local errorText="backup file already exists: canceling backup operation"
if [[ -f "${BACK_UP_LOG_PATH}" ]]; then
echo "" >> "${BACK_UP_LOG_PATH}"
echo "${errorText}" >> "${BACK_UP_LOG_PATH}"
else
echo "${errorText}" > "${BACK_UP_LOG_PATH}"
fi
}
# check to see if th back up tar file already exists - if so let the user know in the log and exit -
# do not continue because we don't know if the user wants to rm the file or not
check_file () {
if [[ -f "${BACK_UP_PATH}.tar.gz" ]]; then
write_file_exists_error
exit 1
fi
}
del_files () {
local filepath="${1}"
local modDate="${2}"
local file="${3}"
local dir="${4}"
local delCutOffDate=$(date -d "$date -7 days" +%m-%d-%Y) # sets date to 7 days ago
if [[ -f "${filepath}" ]]; then # make sure $file is an actual file and not a directory
if [[ "${modDate}" -ot "${delCutOffDate}" ]]; then # Compares the file modified date to the cut off date for deletion - anything older than 7 days
echo " ${file} deleted from ${dir}" >> "${BACK_UP_LOG_PATH}"
echo " ModDate: ${modDate}" >> "${BACK_UP_LOG_PATH}"
echo " Cut Off: ${delCutOffDate}" >> "${BACK_UP_LOG_PATH}"
echo " test: ${modDate} -ot ${delCustOffDate}" >> "${BACK_UP_LOG_PATH}"
rm "${filepath}" >> "${BACK_UP_LOG_PATH}"
fi
fi
}
cycle_files () {
local files=("$@")
local dir="${files[-1]}" # $ is set on the number of arguments, so this wouldn't be $1, it would be $ whatever the last index in the argument array is
# This is because the number of files are dynamic, making the array indexing dynamic. making this way the best to obtain the dir we want
unset 'files[-1]' # remove the directory as filepath prefixes the file with the directory - prefixing a directory to a directory will throw an error
for file in "${files[@]}"; do # for each file in the current directory do the following loop
filepath="${dir}${file}" # prefix the filename with the directory path for file manipulation
modDate=$(date -r "${filepath}" +%m-%d-%Y) # Gets modified date of a file
del_files "${filepath}" "${modDate}" "${file}" "${dir}"
done
}
cycle_dirs () {
local dirs=("$@")
for dir in "${dirs[@]}"; do # for each directory do the following loop
files=($(ls "${dir}")) # list all files in $dir and put them in an array
echo "Enterying: ${dir}" >> "${BACK_UP_LOG_PATH}"
cycle_files "${files[@]}" "${dir}"
done
}
delete_old_files () {
echo "" >> "${BACK_UP_LOG_PATH}"
echo "" >> "${BACK_UP_LOG_PATH}"
echo "The folowing files were deleted:" >> "${BACK_UP_LOG_PATH}"
echo "" >> "${BACK_UP_LOG_PATH}"
dirs=( "${BACK_UP_DIR}" "${BACK_UP_LOG_DIR}" ) # create an array of directories to cycle through for deleting old back up and log files
cycle_dirs "${dirs[@]}"
}
check_file
# Back up files
echo "The following files were backed up:" > "${BACK_UP_LOG_PATH}" # if we have gotten this far we have a clean back up file so lets also do a clean log
echo "" >> "${BACK_UP_LOG_PATH}"
tar -czvf "${BACK_UP_PATH}.tar.gz" "${BACK_UP_LOCATION}" >> "${BACK_UP_LOG_PATH}"
# Delete old log and back up files
delete_old_files
exit 0
The revised code and file for use is available on github: https://github.com/rowlandholden76/Bash-Backup