TUBS/tubs.sh

314 lines
11 KiB
Bash
Raw Normal View History

2022-04-09 01:29:16 +02:00
#!/bin/bash
#============================================================================
#title : TUBS
#description : The Ultimate Backup Script (Linux) Version 3
2022-07-04 23:41:07 +02:00
#author : Janic Voser
2022-04-09 01:29:16 +02:00
#date : 2022-04-08
#updated : 2022-07-04
#version : 3.0
2022-04-09 01:29:16 +02:00
#usage : chmod +x tubs.sh && ./tubs.sh
#notes :
#bash_version :
#============================================================================
# Config
## Configfile
2022-07-04 23:41:07 +02:00
CONFIG_FILE="/etc/tubs/tubs.config" # Any Config File
#CONFIG_FILE="$PWD/tubs.config"
2022-04-09 01:29:16 +02:00
# Functions
## Colorful Information
function blue(){ # The blue color is used for inforation
echo -e '\e[34m'"$1"'\e[0m'
}
function cyan(){ # The cyan color is only used for help
echo -e '\e[0;36m'"$1"'\e[0m'
}
function green(){ # The green color is used for successful steps
echo -e '\e[32m'"$1"'\e[0m'
}
function magenta(){ # The magenta color is used for warnings & important Information
echo -e '\e[35m'"$1"'\e[0m'
}
function red(){ # The red color is used for failed steps
echo -e '\e[31m'"$1"'\e[0m' && exit 1
}
## Critical Error
function critical_error {
red "Critical error during: $1"
}
## Load Config
function load_config {
if [ -e "$CONFIG_FILE" ]
then
blue "Loading Config"
source "$CONFIG_FILE" || critical_error "Reading Configfile"
else
red "Configfile not Found"
fi
}
## Create destination Structure
function create_dst {
if [ "$SSH_REMOTE_DST" == "YES" ]
then
ssh -i "$SSH_REMOTE_KEY_DST" -p "$SSH_REMOTE_PORT_DST" "$SSH_REMOTE_USER_DST@$SSH_REMOTE_HOST_DST" mkdir -p "$BACKUP_DST_FULL" || critical_error "Creating Remote Directory BACKUP_DST_FULL"
ssh -i "$SSH_REMOTE_KEY_DST" -p "$SSH_REMOTE_PORT_DST" "$SSH_REMOTE_USER_DST@$SSH_REMOTE_HOST_DST" mkdir -p "$BACKUP_DST_INC" || critical_error "Creating Remote Directory BACKUP_DST_INC"
else
mkdir -p "$BACKUP_DST_FULL" || critical_error "Creating Directory BACKUP_DST_FULL"
mkdir -p "$BACKUP_DST_INC" || critical_error "Creating Directory BACKUP_DST_INC"
fi
2022-04-09 01:29:16 +02:00
}
## Check destination
function check_dst {
if [ "$SSH_REMOTE_DST" == "YES" ]
2022-04-09 01:29:16 +02:00
then
magenta "This script is currently not able to check if remote Destinations exist"
if ssh -i "$SSH_REMOTE_KEY_DST" -p "$SSH_REMOTE_PORT_DST" "$SSH_REMOTE_USER_DST@$SSH_REMOTE_HOST_DST" [ -e "$BACKUP_DST" ]
then
blue "Remote Backup destinantion existing"
else
red "Remote Backup destination not existing"
fi
ssh -i "$SSH_REMOTE_KEY_DST" -p "$SSH_REMOTE_PORT_DST" "$SSH_REMOTE_USER_DST@$SSH_REMOTE_HOST_DST" mkdir -p "$BACKUP_DST_INC_PATH" || critical_error "Error while creating remote incremental backup-directory ($BACKUP_DST_INC_PATH)"
ssh -i "$SSH_REMOTE_KEY_DST" -p "$SSH_REMOTE_PORT_DST" "$SSH_REMOTE_USER_DST@$SSH_REMOTE_HOST_DST" mkdir -p "$BACKUP_DST_FULL_LOGS" || critical_error "Error while creating remote log directory ($BACKUP_DST_FULL_LOGS)"
2022-04-09 01:29:16 +02:00
else
if [ -e "$BACKUP_DST" ]
then
blue "Backup destinantion existing"
else
red "Backup destination not existing"
fi
mkdir -p "$BACKUP_DST_INC_PATH" || critical_error "Error while creating incremental backup-directory ($BACKUP_DST_INC_PATH)"
mkdir -p "$BACKUP_DST_FULL_LOGS" || critical_error "Error while creating log directory ($BACKUP_DST_FULL_LOGS)"
2022-04-09 01:29:16 +02:00
fi
2022-04-09 01:29:16 +02:00
}
## Check sources local
2022-04-09 01:29:16 +02:00
function check_src {
for src_dir in "${BACKUP_SRC_ARRAY[@]}"
do
if [[ "$src_dir" =~ ^*[/] ]]
then
critical_error "$src_dir is ending with slash please remove it"
fi
if ! [ -d "$src_dir" ]
then
critical_error "$src_dir is not a directory"
fi
green "Source $src_dir is valid"
done
}
## Check Incremental Date
function check_inc {
if [ "$SSH_REMOTE_DST" == "YES" ]
then
check_inc_remote
else
check_inc_local
fi
BACKUP_DST_INC_PATH="$BACKUP_DST_INC/$BACKUP_PREFIX$LAST_BACKUP"
}
## Check Incremental Date
function check_inc_local {
2022-04-09 01:29:16 +02:00
if ! [ -e "$BACKUP_LAST_FILE" ]
then
magenta "Missing last successfull backup file, just using the day before"
LAST_BACKUP="$(date --date="yesterday" "$DATE_FORMAT")"
else
LAST_BACKUP="$(cat "$BACKUP_LAST_FILE")"
if ! [[ $LAST_BACKUP =~ ^[0-9]{4}(-[0-9]{2}){2}_[0-9]{2}-[0-9]{2} ]]
then
magenta "Content of last successfull backup file was not valid"
LAST_BACKUP="$(date --date="yesterday" "$DATE_FORMAT")"
fi
fi
}
## Check Incremental Date
function check_inc_remote {
if ! ssh -i "$SSH_REMOTE_KEY_DST" -p "$SSH_REMOTE_PORT_DST" "$SSH_REMOTE_USER_DST@$SSH_REMOTE_HOST_DST" [ -e "$BACKUP_LAST_FILE" ]
then
magenta "Missing last successfull backup file, just using the day before"
LAST_BACKUP="$(date --date="yesterday" "$DATE_FORMAT")"
else
LAST_BACKUP="$(ssh -i "$SSH_REMOTE_KEY_DST" -p "$SSH_REMOTE_PORT_DST" "$SSH_REMOTE_USER_DST@$SSH_REMOTE_HOST_DST" cat "$BACKUP_LAST_FILE")"
if ! [[ $LAST_BACKUP =~ ^[0-9]{4}(-[0-9]{2}){2}_[0-9]{2}-[0-9]{2} ]]
then
magenta "Content of last successfull backup file was not valid"
LAST_BACKUP="$(date --date="yesterday" "$DATE_FORMAT")"
fi
fi
2022-04-09 01:29:16 +02:00
}
## Check Prerequirements
function check_prereq {
command -v rsync &> /dev/null || critical_error "Missing rsync"
green "All requirements are saturated"
}
## Last successful backup
function last_backup {
if [ "$SSH_REMOTE_DST" == "YES" ]
then
last_backup_remote
else
last_backup_local
fi
}
### Last successful backup
function last_backup_local {
2022-04-09 01:29:16 +02:00
if touch "$BACKUP_LAST_FILE" &> /dev/null
then
echo "$BACKUP_DATE" > "$BACKUP_LAST_FILE"
else
critical_error "Can not write Last successful backup file"
fi
}
### Last successful backup
function last_backup_remote {
if ssh -i "$SSH_REMOTE_KEY_DST" -p "$SSH_REMOTE_PORT_DST" "$SSH_REMOTE_USER_DST@$SSH_REMOTE_HOST_DST" touch "$BACKUP_LAST_FILE" &> /dev/null
then
echo "$BACKUP_DATE" | ssh -i "$SSH_REMOTE_KEY_DST" -p "$SSH_REMOTE_PORT_DST" "$SSH_REMOTE_USER_DST@$SSH_REMOTE_HOST_DST" -T "cat > $BACKUP_LAST_FILE"
else
critical_error "Can not write Last successful backup file"
fi
}
2022-04-09 01:29:16 +02:00
## Backup all
function backup_all {
if [ "$SSH_REMOTE_DST" == "YES" ]
then
backup_all_remote
else
backup_all_local
fi
}
## Backup all local
function backup_all_local {
2022-04-09 01:29:16 +02:00
blue "Starting Backup Processes"
for src_dir in "${BACKUP_SRC_ARRAY[@]}"
do
src_dir_name="$(echo "$src_dir" | rev | cut -d / -f 1 | rev)"
cat << EOF >> "$BACKUP_DST_FULL_LOGS/$src_dir_name.log"
################################################################################
#############################TUBS $BACKUP_DATE##############################
################################################################################
EOF
rsync "$RSYNC_ARGS" --backup --delete --backup-dir="$BACKUP_DST_INC_PATH/" "$src_dir" "$BACKUP_DST_FULL" >> "$BACKUP_DST_FULL_LOGS/$src_dir_name.log" &
2022-04-09 01:29:16 +02:00
done
green "All backup processes started successfull"
blue "Waiting for processes to finish"
# wait for all pids
jobs=$(jobs -p)
for process in $jobs
do
wait "$process" || critical_error "Process: $process failed"
done
green "All Processes finished"
}
## Backup all remote
function backup_all_remote {
blue "Starting Backup Processes"
for src_dir in "${BACKUP_SRC_ARRAY[@]}"
do
src_dir_name="$(echo "$src_dir" | rev | cut -d / -f 1 | rev)"
ssh -i "$SSH_REMOTE_KEY_DST" -p "$SSH_REMOTE_PORT_DST" "$SSH_REMOTE_USER_DST@$SSH_REMOTE_HOST_DST" -T "cat << EOF >> \"$BACKUP_DST_FULL_LOGS/$src_dir_name.log\"
################################################################################
#############################TUBS $BACKUP_DATE##############################
################################################################################
EOF
"
rsync "$RSYNC_ARGS" -e "ssh -p $SSH_REMOTE_PORT_DST -i $SSH_REMOTE_KEY_DST" --backup --delete --backup-dir="$BACKUP_DST_INC_PATH/" "$src_dir" "$SSH_REMOTE_USER_DST@$SSH_REMOTE_HOST_DST:$BACKUP_DST_FULL" | ssh -i "$SSH_REMOTE_KEY_DST" -p "$SSH_REMOTE_PORT_DST" "$SSH_REMOTE_USER_DST@$SSH_REMOTE_HOST_DST" -T "cat >> \"$BACKUP_DST_FULL_LOGS/$src_dir_name.log\"" &
done
green "All backup processes started successfull"
blue "Waiting for processes to finish"
# wait for all pids
jobs=$(ssh -i "$SSH_REMOTE_KEY_DST" -p "$SSH_REMOTE_PORT_DST" "$SSH_REMOTE_USER_DST@$SSH_REMOTE_HOST_DST" jobs -p)
for process in $jobs
do
ssh -i "$SSH_REMOTE_KEY_DST" -p "$SSH_REMOTE_PORT_DST" "$SSH_REMOTE_USER_DST@$SSH_REMOTE_HOST_DST" wait "$process" || critical_error "Process: $process failed"
done
green "All Processes finished"
}
2022-04-09 01:29:16 +02:00
## Pre Backup Script
function pre_backup_script {
if [ -e "$PRE_BACKUP_SCRIPT" ]
then
if [ -x "$PRE_BACKUP_SCRIPT" ]
then
blue "Executing Pre-Backup-Script"
$PRE_BACKUP_SCRIPT
green "Pre-Backup-Script finished"
else
magenta "Pre-Backup-Script is not executable"
fi
else
blue "No Pre-Backup-Script found"
fi
}
## Post Backup Script
function post_backup_script {
if [ -e "$POST_BACKUP_SCRIPT" ]
then
if [ -x "$POST_BACKUP_SCRIPT" ]
then
blue "Executing Post-Backup-Script"
$POST_BACKUP_SCRIPT
green "Post-Backup-Script finished"
else
magenta "Post-Backup-Script is not executable"
fi
else
blue "No Pre-Backup-Script found"
fi
}
## Generate Variables
load_config # Load config first (Variables are dependent on it)
BACKUP_DATE="$(date "$DATE_FORMAT")"
BACKUP_DST_FULL="$BACKUP_DST/FULL"
BACKUP_DST_FULL_LOGS="$BACKUP_DST_FULL/logs"
BACKUP_DST_INC="$BACKUP_DST/INCREMENTAL"
BACKUP_LAST_FILE="$BACKUP_DST/LAST_SUCCESSFULL_BACKUP"
# Main Script
## Load config
if [ -n "$1" ]
then
case "$1" in
help)
cyan "Execute this script with one of the following arguments"
cyan " - help --> Display help (your reading it right now)"
cyan " - init --> Initialize the backup Structure"
cyan " - backup --> Do the accual backup"
cyan " - restore --> Restore all the data from a certain day"
;;
init)
blue "Starting initialisation"
create_dst
blue "Initialisation was successfull"
;;
backup)
green "TUBS started"
check_inc
check_dst
check_src
check_prereq
last_backup
pre_backup_script
backup_all
post_backup_script
green "TUBS finished"
;;
restore)
magenta "I am kinda sorry this is not implemented yet"
exit
;;
*)
red "Your supplied argument was not valid use help if you don't know what you are doing"
;;
esac
exit
else
cyan "Please supply a valid argument or execute with help flag"
fi