HEX
Server: Apache
System: Linux viper.innovativeinternet.net 4.18.0-553.80.1.lve.el8.x86_64 #1 SMP Wed Oct 22 19:29:36 UTC 2025 x86_64
User: thetradingroom (1095)
PHP: 8.3.25
Disabled: exec,passthru,shell_exec,system
Upload Files
File: //ibin/ibackup
#!/bin/bash
#
# ibackup
#
# Written by - Jack Sasportas -  Jack@innovativeinternet.com
#
# Backup Data Files based on SOURCE values utilizing rsync and hard links and cleans up files older than
# 90 days using the cleanup script.
#
# Usage: ibackup [backup_type] [destination] [debug]
#
# [backup_type] - data type: data, db, config
# [destination] - backup destination: local, external, remote
# [debug]       - Optional: pass "debug" to display the command without executing
#
# local    - creates backup on the calling server
# external - creates backup in the local data center on a different server
# remote   - creates backup in the remote data center
#
# Color codes:
# light blue - informational
# navy blue  - executed command
# purple     - backup communications
# red        - error
#
#########################################################################################################
# Version 5.2
#
# Updated:
# 10-18-2024 - Enhanced email notifications to include detailed information
# 10-18-2024 - Added error handling and enhanced email notifications
# 10-18-2024 - Script renamed to 'ibackup', moved server configurations to /etc/ibackup_config.sh
#              Made server configuration loading dynamic to improve efficiency
# 12-12-2023 - Changed gallardo to firebird as remote server.
# 07-04-2023 - Added code for different cleanup for external DB files vs folders
# 06-29-2018 - Added debug functionality with "debug" parameter
# 06-27-2017 - cPanel customizations
# 03-08-2018 - Fixed backup path
# 03-14-2018 - Fixed deletion of log files
# 12-23-2019 - Added Disk Check Function with email notification
# 12-01-2020 - Enhanced Email Notification
# 12-29-2021 - Modified database folder to db
#
#########################################################################################################

# Source configuration file
CONFIG_FILE='/ibin/ibackup_config.sh'
if [[ ! -f $CONFIG_FILE ]]; then
    echo "Configuration file $CONFIG_FILE not found!"
    exit 1
fi
source $CONFIG_FILE

# Function to send email notifications
send_email() {
    local subject="$1"
    local message="$2"
    echo -e "$message" | mail -s "$subject" -r "$FROM_EMAIL" "$NOTIFICATION_EMAIL"
}

backup_list() {
    local home_directory="/home"
    local output_file="/ibin/cpbackup_source.txt"

    if [[ ! -d "$home_directory" ]]; then
        echo "Home directory $home_directory does not exist!"
        exit 1
    fi

    cd "$home_directory" || exit 1
    find . -mindepth 1 -maxdepth 1 -type d -printf "$home_directory/%f\n" > "$output_file"

    echo "Folder list has been saved to $output_file"
}

# Color codes
LBLUE='\e[104m'
PURPLE='\e[37;45m'
NBLUE='\e[37;44m'
RED='\e[41m'
CLEAR='\033[0m\n'

date=$(date "+%Y-%m-%d_%H%M%S")
readable_date=$(date)
SSERVER=$(hostname | perl -p -e 's/(.*?)\..*/$1/')

BACKUP_LOG="/var/log/cpbackup/${SSERVER}-$1-$2-$date"
BACKUP_SOURCE='/ibin/cpbackup_source.txt'
BACKUP_EXCLUDE='/ibin/cpbackup_exclude.txt'
BACKUP_FOLDER='/backup'

# Notification Variables
NOTIFICATION_EMAIL='jack@innovativeinternet.com'
FROM_EMAIL='BackupAdmin@InnovativeInternet.net'

BACKUP_DISK='/backup'
BACKUP_DISK_USED=$(df -Ph | grep $BACKUP_DISK | awk '{print $5}' | tr -d '%')
MAX=90

OPTS='-e ssh -aP --delete --ignore-errors'

# Check Disk Space before executing Job
if [[ $BACKUP_DISK_USED -ge $MAX ]]; then
    subject="Backup Job on $SSERVER Stopped - Disk Full ($BACKUP_DISK_USED%)"
    message="Backup Job on $SSERVER STOPPED!\nRun: $readable_date\nDisk usage on $BACKUP_DISK is at $BACKUP_DISK_USED%.\nPlease free up space."
    send_email "$subject" "$message"
    echo -e "${RED}Backup Job ABORTED on $SSERVER because Disk $BACKUP_DISK is $BACKUP_DISK_USED% full!${CLEAR}"
    exit 1
fi

case $SSERVER in
    maggie|g2|garage)
        echo -e "${LBLUE}Skipping backup list generation for $SSERVER${CLEAR}"
        ;;
    *)
        backup_list
        ;;
esac

# Determine Backup Server from configuration
echo -e "${LBLUE}Determining Backup Server${CLEAR}"

# Build variable names based on server name
locserver_var="${SSERVER}_locserver"
extserver_var="${SSERVER}_extserver"
remserver_var="${SSERVER}_remserver"
uniqdns_var="${SSERVER}_uniqdns"

# Check if the variables exist
if [[ -z "${!locserver_var}" ]]; then
    echo -e "${RED}EXIT: No Matching Server Configuration for $SSERVER${CLEAR}"
    exit 1
fi

# Assign the variables dynamically using variable indirection
LocServer="${!locserver_var}"
ExtSERVER="${!extserver_var}"
RemSERVER="${!remserver_var}"
UNIQDNS="${!uniqdns_var}"

# Determine Backup Type, Source, and Prefix
case $1 in
    data)
        if [[ ! -f $BACKUP_SOURCE ]]; then
            echo -e "${RED}Backup source file $BACKUP_SOURCE not found!${CLEAR}"
            exit 1
        fi
        SOURCE=$(cat $BACKUP_SOURCE)
        TYPE='data'
        PREFIX=''
        ;;
    ibin)
        SOURCE='/ibin /etc'
        TYPE='ibin'
        PREFIX=''
        ;;
    db)
        SOURCE="/backup/${SSERVER}/db/"
        if [[ ! -d $SOURCE ]]; then
            echo -e "${RED}Database backup directory $SOURCE does not exist!${CLEAR}"
            exit 1
        fi
        TYPE='db'
        PREFIX=''
        ;;
    config)
        SOURCE="/var/named /root /ibin /etc /var/spool/cron ${UNIQDNS}"
        TYPE='configs'
        PREFIX=''
        ;;
    *)
        echo -e "${RED}ERROR: Invalid Backup Type${CLEAR}"
        exit 1
        ;;
esac

# Determine Backup Destination
echo -e "${LBLUE}Determining Backup Destination Paths${CLEAR}"
case $2 in
    local)
        echo -e "${NBLUE}Backing up: $SSERVER to: $LocServer${CLEAR}"
        TPATH_CURRENT="${BACKUP_FOLDER}/${SSERVER}/$TYPE"
        TPATH_BACKUP="${BACKUP_FOLDER}/${SSERVER}/$TYPE"
        mkdir -p $TPATH_CURRENT || { echo -e "${RED}Failed to create directory $TPATH_CURRENT${CLEAR}"; exit 1; }
        ;;
    external)
        echo -e "${NBLUE}Backing up: $SSERVER to: $ExtSERVER${CLEAR}"
        TPATH_CURRENT="${BACKUP_FOLDER}/${SSERVER}/$TYPE"
        TPATH_BACKUP="$ExtSERVER:${BACKUP_FOLDER}/${SSERVER}/$TYPE"
        ssh $ExtSERVER "mkdir -p $TPATH_CURRENT" || { echo -e "${RED}SSH command failed on $ExtSERVER${CLEAR}"; exit 1; }
        ;;
    remote)
        echo -e "${NBLUE}Backing up: $SSERVER to: $RemSERVER${CLEAR}"
        TPATH_CURRENT="${BACKUP_FOLDER}/${SSERVER}/$TYPE"
        TPATH_BACKUP="$RemSERVER:${BACKUP_FOLDER}/${SSERVER}/$TYPE"
        ssh $RemSERVER "mkdir -p $TPATH_CURRENT" || { echo -e "${RED}SSH command failed on $RemSERVER${CLEAR}"; exit 1; }
        ;;
    *)
        echo -e "${RED}ERROR: No Backup Destination Specified${CLEAR}"
        exit 1
        ;;
esac

{
    echo "----------------------------------------------------------------------------------------------------------------------------------------------------"
    echo "---- Server:$SSERVER Backup Type:$TYPE Dest:$2 -- Location:$TPATH_CURRENT/$PREFIX$date ------------------------------------"
    echo "----------------------------------------------------------------------------------------------------------------------------------------------------"
} >> $BACKUP_LOG

if [[ $3 == "debug" ]]; then
    echo -e "${LBLUE}Display Command Mode${CLEAR}"
    echo -e "${NBLUE}Backing Up $SOURCE/${CLEAR}"
    echo "Command: nice -n 19 rsync $OPTS --link-dest=$TPATH_CURRENT/current $SOURCE $TPATH_BACKUP/$PREFIX$date --exclude-from=$BACKUP_EXCLUDE --log-file=$BACKUP_LOG"
    exit 0
fi



#  OLD
###echo -e "${LBLUE}Executing Backup${CLEAR}"
###echo -e "${NBLUE}Backing Up $SOURCE/${CLEAR}"
###nice -n 19 rsync $OPTS --link-dest=$TPATH_CURRENT/current $SOURCE $TPATH_BACKUP/$PREFIX$date --exclude-from=$BACKUP_EXCLUDE --log-file=$BACKUP_LOG
###RSYNC_EXIT_CODE=$?

###if [[ $RSYNC_EXIT_CODE -ne 0 ]]; then
###    subject="Backup Job on $SSERVER Failed"
###    message="Backup Job on $SSERVER FAILED!\nRun: $readable_date\nBackup Type: $TYPE\nDestination: $2\nRsync exited with code $RSYNC_EXIT_CODE.\nCheck the backup log at $BACKUP_LOG for details."
###    send_email "$subject" "$message"
###    echo -e "${RED}Backup failed with rsync exit code $RSYNC_EXIT_CODE${CLEAR}"
###    exit 1
###fi

# OLD END



echo -e "${LBLUE}Executing Backup${CLEAR}"
echo -e "${NBLUE}Backing Up $SOURCE/${CLEAR}"

# Ensure we capture rsync's real exit code even through the pipe
set -o pipefail

nice -n 19 rsync $OPTS --itemize-changes --progress \
  --link-dest="$TPATH_CURRENT/current" \
  $SOURCE "$TPATH_BACKUP/$PREFIX$date" \
  --exclude-from="$BACKUP_EXCLUDE" \
  --log-file="$BACKUP_LOG" \
  | awk '
    function color(c,s){ printf("%s%s\033[0m\n", c, s) }
    /^\*deleting/               { color("\033[31m",$0); next }   # red: deletions
    /^>f\+\+\+\+\+\+\+/         { color("\033[32m",$0); next }   # green: new files
    /^>f\./                     { color("\033[33m",$0); next }   # yellow: updated files
    /^cd\+\+\+\+\+\+\+/         { color("\033[36m",$0); next }   # cyan: new directories
    /^[>cshd][^ ]* /            { color("\033[32m",$0); next }   # green: other transfers
    /^\.[^ ]* /                 { color("\033[90m",$0); next }   # gray: metadata-only changes
    /^[a-zA-Z0-9\/].*\/$/       { color("\033[36m",$0); next }   # cyan: directory names
    /^[a-zA-Z0-9].*[^\/]$/      { color("\033[37m",$0); next }   # white: file names
    { print }                                                   # anything else (progress, etc.)
  '

RSYNC_EXIT_CODE=${PIPESTATUS[0]}



# Cleanup Folder Structure
echo -e "${LBLUE}Cleanup Folder Structure Process${CLEAR}"
case $2 in
    local)
        rm -rf $TPATH_CURRENT/current
        ln -s $TPATH_CURRENT/$PREFIX$date $TPATH_CURRENT/current
        ;;
    external)
        ssh $ExtSERVER "/bin/rm -rf $TPATH_CURRENT/current && ln -s $TPATH_CURRENT/$PREFIX$date $TPATH_CURRENT/current" || {
            echo -e "${RED}Failed to update current symlink on $ExtSERVER${CLEAR}"
            exit 1
        }
        ;;
    remote)
        ssh $RemSERVER "/bin/rm -rf $TPATH_CURRENT/current && ln -s $TPATH_CURRENT/$PREFIX$date $TPATH_CURRENT/current" || {
            echo -e "${RED}Failed to update current symlink on $RemSERVER${CLEAR}"
            exit 1
        }
        ;;
    *)
        echo -e "${RED}ERROR: No Backup Type Selected${CLEAR}"
        exit 1
        ;;
esac

# Cleanup Old Backups
echo -e "${LBLUE}Deleting Older Backups${CLEAR}"
cleanup_command="/ibin/cleanup $TPATH_CURRENT"
if [[ $1 == "db" ]]; then
    cleanup_command="/ibin/cleanup-files $TPATH_CURRENT"
fi

case $2 in
    local)
        eval $cleanup_command || { echo -e "${RED}Cleanup command failed locally${CLEAR}"; exit 1; }
        ;;
    external)
        ssh $ExtSERVER "$cleanup_command" || { echo -e "${RED}Cleanup command failed on $ExtSERVER${CLEAR}"; exit 1; }
        ;;
    remote)
        ssh $RemSERVER "$cleanup_command" || { echo -e "${RED}Cleanup command failed on $RemSERVER${CLEAR}"; exit 1; }
        ;;
    *)
        echo -e "${RED}ERROR: No Backup Destination Selected${CLEAR}"
        exit 1
        ;;
esac

# Cleanup Old Log Files
echo -e "${LBLUE}Deleting Older Log Files${CLEAR}"
/ibin/cleanup-files /var/log/cpbackup/ || { echo -e "${RED}Failed to clean up old log files${CLEAR}"; exit 1; }

# Send success email notification
subject="Backup Job on $SSERVER Completed Successfully"
message="Backup Job on $SSERVER completed successfully.\nRun: $readable_date\nBackup Type: $TYPE\nDestination: $2\nLog File: $BACKUP_LOG"
send_email "$subject" "$message"

exit 0