#!/bin/bash ######################################################################## #### Script Name: rbxi #### Version: 2.7.5 #### Date: 2023-09-16 #### Copyright (C) Harald Hope 2006-2023 #### #### This program is free software; you can redistribute it and/or modify it under #### the terms of the GNU General Public License as published by the Free Software #### Foundation; either version 3 of the License, or (at your option) any later version. #### #### This program is distributed in the hope that it will be useful, but WITHOUT #### ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #### FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. #### #### Get the full text of the GPL here: http://www.gnu.org/licenses/gpl.txt #### #### This is an rdiff-backup/rsync script which helps automate the backup process #### Requires companion excludes-....txt files to run, those must be in the rbxi-data #### directory #### #### rbxi.tar.bz2 package download URL: http://smxi.org/rb [contains all needed files] #### Script Home page: http://techpatterns.com/forums/about831.html ######################################################################## ######################################################################## #### CHANGES #### 2.7.5 2023-09-16 - changed to codeberg.org urls for -U updates. #### 2.7.4 2021-08-04 - added 'sync' to force writes to disk. Removed branch #### updaters which pointed to dead urls. Updated -U to use github urls. #### 2.7.3 2015-02-20 - updated date formats to: YYYY-MM-DD, fixed -J restart bug #### that made rbxi fail to return proper exit code on error after restart #### 2.7.2 4 September 2009 - last stable ######################################################################## #### VARIABLES #### Make sure to change these to fit your installation ######################################################################## ######################################################################## #### SCRIPT PATH VARIABLES ####-------------------------------------------------------------------- # Basic script layout markers BA='==================================================================' LI='------------------------------------------------------------------' ### if you do need to change one of these, make sure to change it in the ### user values file: rbxi-data/rbxi-values, not here, or you might lose ### your changes if you update this script. ### Script names/paths # set this as absolute path for cron jobs if you need to, you'll have to # update this manually every time you update the script: LSOF='lsof' LOGFILE_DIR='/var/log/' SELF_CONFIGS='/etc/rbxi.conf' SELF_NAME='rbxi' SELF_DATA='/rbxi-data/' SELF_README='readme-rbxi.htm' SELF_VALUES='rbxi-values' # http://forums.macosxhints.com/archive/index.php/t-73839.html # note, no other method works reliably to get the true script path, not dirname $0. if type $LSOF &>/dev/null;then SELF_PATH=$( dirname $( $LSOF -p $$ | grep 'REG' | grep -Eo "/.*$(basename $0)$" ) ) # checking if the dirname method works elif [ -d "$( dirname $0 )$SELF_DATA" ];then SELF_PATH=$( dirname $0 ) fi # in worst cases, you can manually set the script directory path here, uncomment and make the path # explicit. Must not end with /, and must be the full path of the rbxi directory rbxi came with. # you'll have to update this manually every time you update the script: # example: SELF_PATH='/home/fred/scripts/rbxi' # SELF_PATH='' SELF_DATA_DIR="$SELF_PATH$SELF_DATA" SELF_VERSION_NUMBER=$(grep -im 1 'version:' $SELF_PATH/$SELF_NAME | awk '{print $3}') SELF_DOWNLOAD='https://codeberg.org/smxi/rbxi/raw/branch/master/' SELF_DOWNLOAD_DEV='https://smxi.org/rb/' #### EXCLUDE LIST FILE NAMES # NOTE: can be a blank file, but most be located in same directory as rbxi # if you want them in a different directory, use absolute system paths. EXCLUDE_ROOT='excludes-root.txt' EXCLUDE_HOME='excludes-home.txt' EXCLUDE_DATA_1='excludes-data-1.txt' EXCLUDE_DATA_2='excludes-data-2.txt' EXCLUDE_DATA_3='excludes-data-3.txt' EXCLUDE_DATA_4='excludes-data-4.txt' EXCLUDE_DATA_5='excludes-data-5.txt' EXCLUDE_DATA_6='excludes-data-6.txt' EXCLUDE_DATA_7='excludes-data-7.txt' EXCLUDE_DATA_8='excludes-data-8.txt' EXCLUDE_DATA_9='excludes-data-9.txt' EXCLUDE_DATA_10='excludes-data-10.txt' EXCLUDE_ROOT_RS='excludes-root-rsync.txt' EXCLUDE_HOME_RS='excludes-home-rsync.txt' EXCLUDE_DATA_1_RS='excludes-data-1-rsync.txt' EXCLUDE_DATA_2_RS='excludes-data-2-rsync.txt' EXCLUDE_DATA_3_RS='excludes-data-3-rsync.txt' EXCLUDE_DATA_4_RS='excludes-data-4-rsync.txt' EXCLUDE_DATA_5_RS='excludes-data-5-rsync.txt' EXCLUDE_DATA_6_RS='excludes-data-6-rsync.txt' EXCLUDE_DATA_7_RS='excludes-data-7-rsync.txt' EXCLUDE_DATA_8_RS='excludes-data-8-rsync.txt' EXCLUDE_DATA_9_RS='excludes-data-9-rsync.txt' EXCLUDE_DATA_10_RS='excludes-data-10-rsync.txt' ######################################################################## #### USER SPECIFIC VARIABLES - REQUIRES rbxi-data/rbxi-values file ####-------------------------------------------------------------------- # initializing user defined functions/scripted actions/variables just to be safe, # must be prior to script rbxi-values sourcing CONSOLE_BROWSER='' EMAIL_START_ACTION='' EMAIL_FINISH_ACTION='' EMAIL_ERROR_ACTION='' PRE_MOUNT_FUNCTION='' POST_MOUNT_FUNCTION='' POST_UMOUNT_FUNCTION='' # variables that can be overridden in rbxi-values but which are commented out LOGFILE_SIZE=100 ## add in user variable values, sticky value file # missing test will occur a bit later if [ -f "$SELF_DATA_DIR$SELF_VALUES" ];then source $SELF_DATA_DIR$SELF_VALUES fi ### See the file rbxi-data/rbxi-values for variable lists and how to ### set them. That file will be the actual data used. ### rbxi cannot run without the user data values file: rbxi-data/rbxi-values ######################################################################## #### STATIC VARIABLES, SHOULD NOT REQUIRE CHANGES ####-------------------------------------------------------------------- #### INITIALIZE VARIABLES TO BE SET ELSEWHERE HOME_BACKUP='' ROOT_BACKUP='' # these are optional, only used if DATA_x_DIR is/are set DATA_1_BACKUP='' DATA_2_BACKUP='' DATA_3_BACKUP='' DATA_4_BACKUP='' DATA_5_BACKUP='' DATA_6_BACKUP='' DATA_7_BACKUP='' DATA_8_BACKUP='' DATA_9_BACKUP='' DATA_10_BACKUP='' # backup command string holders HOME_BU_COMMAND='' ROOT_BU_COMMAND='' DATA_1_BU_COMMAND='' DATA_2_BU_COMMAND='' DATA_3_BU_COMMAND='' DATA_4_BU_COMMAND='' DATA_5_BU_COMMAND='' DATA_6_BU_COMMAND='' DATA_7_BU_COMMAND='' DATA_8_BU_COMMAND='' DATA_9_BU_COMMAND='' DATA_10_BU_COMMAND='' # set initial value ENDING_1='...' ENDING_2='...' # for timer function START_TIME=$( date +%s ) # initialize internal booleans B_CLONE_HOME='false' B_CLONE_ROOT='false' B_CLONE_DATA_1='false' B_CLONE_DATA_2='false' B_CLONE_DATA_3='false' B_CLONE_DATA_4='false' B_CLONE_DATA_5='false' B_CLONE_DATA_6='false' B_CLONE_DATA_7='false' B_CLONE_DATA_8='false' B_CLONE_DATA_9='false' B_CLONE_DATA_10='false' B_DELETE_STATUS='false' B_DRY_RUN='false' B_IS_CLONE='false' # initialize globals to be set later BACKUP_CLEAR='' BACKUP_DURATION='' # only for logging/history purposes BACKUP_JOB_NAME='' BACKUP_JOB_NU='none' CLONE_SOURCE_DIR='' DELETION_TEXT='' # spinning wheel pid value GET_PID='' RSYNC_DELETE='' SELF_OPTIONS="$@" ################################################################### ##### Functions ################################################################### #### ------------------------------------------------------------------- #### Options/Parameters #### ------------------------------------------------------------------- show_options() { if [ "$1" == 'err' ];then echo 'You entered an invalid option. Please use one of the following only:' fi echo '-A Add backup component. Overrides user set B_SKIP_DATA.. (d|h|hr|r|1-10)' echo ' d - add all DATA; h - add HOME; r - add ROOT; add DATA 1-10' echo '-b Automatic backup, non interactive.' echo '-B Change default backup directory (1-10).' echo '-c Automatic backup, clean older files, then runs non-interactive backup.' echo '-C (rsync only) Clone root/home. Skips all data backups. Moves files directly to mounted location' echo ' Sets the main mount subdirectory to '', then transfers files directly into that directory.' echo ' Takes parameters: (h|r|1-10). Clone root, home, or a data direcory.' echo '-d Automatic backup and delete, non interactive.' echo '-D Change default backup sub directory (1-10).' echo '-E Requires <1-10:1-10:1-10> for script start, finish, or error actions. Must be' echo ' one or more, but does not need to be all three. Actions are user created. See readme for how-to.' echo '-j Set script color scheme -j [0-5]: 0 - no colors; 1 - default, ok for dark/light or light/dark' echo ' 2 - fancy dark on light; 3 - basic light on dark; 4 - fancy light on dark; 5 - smxi style' echo '-J Start preset backup job (1-10). Cannot be used with any other option.' echo '-l Use logging. Will override user rbxi-values setting.' echo "-L Create symbolic link in /usr/local/bin to $SELF_NAME" echo '-m Skip the mounting option.' echo '-M use alternate mount/umount set (1-10)' echo '-o Override default backup application.' echo '-P Requires <1-10:1-10:1-10> for pre mount, post mount, or post umount extra functions. Must be' echo ' one or more, but does not need to be all three. Functions are user created. See readme for how-to.' echo '-r Trigger --dry-run for rsync. This simulates the backup, but does not actually run it.' echo '-R Show script readme file. Requires one of these console browsers (can also be set in rbxi-values):' echo ' links2 elinks w3m links lynx' echo '-s Show spinning wheel indicator.' echo '-S Skip backup component (d|h|hr|1-10)' echo ' d - skip all DATA; h - skip HOME; r - skip ROOT; skip DATA 1-10' echo '-U Update script manually from git server.' echo '-v Show script version and last used information.' echo '-V Use alternate rbxi-values file. Syntax: rbxi-values-' echo ' File must be located in rbxi-data, and must have the syntax of: rbxi-values-' echo '-h This help menu' echo echo 'In general, avoid using A, D, M, S unless you are creating a backup job -J, or if you want' echo 'temporarily skip (-S) or add (-A) a specific directory.' echo echo '-S and -A can be used repeatedly, like so: -S 2 -S 5 -S 9' echo 'Remember, -A should only be used to override SKIP... that has been set in rbxi-values.' echo '-C overrides -A which overrides -S. -C will only clone the specific directory you set,' echo 'directly to the destination directory, and switches off all other backup directories.' echo '-C overrides -D, or default backup subdirectory, and sets it to null.' echo '-D overrides default main mount backup directory, and uses that for -M' exit 0 } ### this is not in a function because these variables need to be set on startup # only use b or d, not both together. If you use both your old backups will be deleted. # args: $1 - $@ - all args # -A and -S can iterate repeatedly get_options() { local opt='' setDirectory='' setSubDir='' setMount='' setPrePost='' local setFullAdds='' setFullSkips='' setCloneData='' setEmailer='' while getopts :A:bB:cC:dD:E:hj:J:LlmM:o:P:rRsS:UvV:z:!: opt do case $opt in h) show_options ;; A) if [ -n "$( grep -E '^(d|h|r|rh|hr|[1-9]|10)$' <<< $OPTARG )" ];then setFullAdds="$setFullAdds $OPTARG" else error_handler 13 "-$opt $OPTARG" fi ;; b) B_DO_BACKUP='true' ;; B) if [ -n "$( grep -E '^([1-9]|10)$' <<< $OPTARG )" ];then setDirectory="$OPTARG" else error_handler 13 "-$opt $OPTARG" fi ;; c) B_CLEAN_OLDER='true' B_DO_BACKUP='true' ;; C) if [ -n "$( grep -E '^(r|h|[1-9]|10)$' <<< $OPTARG )" ];then setCloneData=$OPTARG B_IS_CLONE='true' else error_handler 13 "-$opt $OPTARG" fi ;; d) B_DELETE_BACKUP='true' B_DO_BACKUP='true' ;; D) if [ -n "$( grep -E '^([1-9]|10)$' <<< $OPTARG )" ];then setSubDir="$OPTARG" else error_handler 13 "-$opt $OPTARG" fi ;; E) if [ -n "$( grep -E '^([1-9]|10)?:([1-9]|10)?:([1-9]|10)?$' <<< $OPTARG )" ];then setEmailer="$OPTARG" else error_handler 13 "-$opt $OPTARG" fi ;; j) if [ -n "$( grep -E '^([0-5])$' <<< $OPTARG )" ];then COLOR_SCHEME=$OPTARG set_self_colors else error_handler 13 "-$opt $OPTARG" fi ;; J) if [ -n "$( grep -E '^([1-9]|10)$' <<< $OPTARG )" ];then set_or_print_backup_job "$OPTARG" 'set' else error_handler 13 "-$opt $OPTARG" fi ;; l) B_LOGGING='true' ;; L) create_symbolic_link exit 0 ;; m) B_SKIP_MOUNT='true' ;; M) if [ -n "$( grep -E '^([1-9]|10)$' <<< $OPTARG )" ];then setMount="$OPTARG" else error_handler 13 "-$opt $OPTARG" fi ;; o) if [ -n "$( grep -E '^(rd|rs)$' <<< $OPTARG )" ];then case $OPTARG in rd) BACKUP_APP='rdiff-backup' ;; rs) BACKUP_APP='rsync' ;; esac else error_handler 13 "-$opt $OPTARG" fi ;; P) if [ -n "$( grep -E '^([1-9]|10)?:([1-9]|10)?:([1-9]|10)?$' <<< $OPTARG )" ];then setPrePost="$OPTARG" else error_handler 13 "-$opt $OPTARG" fi ;; r) B_DRY_RUN='true' ;; R) show_self_readme exit ;; s) B_SPINNING_WHEEL='true' ENDING_1=': ' ENDING_2=', watch the spinning wheel: ' ;; S) if [ -n "$( grep -E '^(d|h|r|rh|hr|[1-9]|10)$' <<< $OPTARG )" ];then setFullSkips="$setFullSkips $OPTARG" else error_handler 13 "-$opt $OPTARG" fi ;; U) self_updater "$SELF_DOWNLOAD" 'git server' ;; v) print_version_info 'opt' exit 0 ;; V) # construct new user values file name, then test it, load it SELF_VALUES="$SELF_VALUES-$OPTARG" if [ -f "$SELF_DATA_DIR$SELF_VALUES" ];then source $SELF_DATA_DIR$SELF_VALUES set_self_colors check_self_requires else error_handler 22 fi ;; # set_or_print_backup_job will relaunch with job options and -z has the bu job nu for output z) if [ -n "$( grep -E '^([1-9]|10)$' <<< $OPTARG )" ];then BACKUP_JOB_NU=$OPTARG fi ;; !) # test for various supported methods case $OPTARG in 1) B_TESTING_1='true' ;; 2) B_TESTING_2='true' ;; 3) B_TESTING_1='true' B_TESTING_2='true' ;; 10) self_updater "$SELF_DOWNLOAD_DEV" 'dev server' ;; http*) self_updater "$OPTARG" 'alt server' ;; *) error_handler 11 "-$opt $OPTARG" ;; esac ;; *) error_handler 7 "-$OPTARG" ;; esac done # note, because mount will use the first value, I have to set this here, to # ensure the proper order. Or you can just set the stuff manually in your rbxi-values file # Clone -C overrides Adds -A override skips -S. -A and -S can handle multiple iterations. # -C overrides -D, backup subdirectory, and sets it to null # -D overrides default main backup directory for -M if [ -n "$setDirectory" ];then set_backup_mount_point "$setDirectory" fi if [ -n "$setSubDir" ];then set_backup_mount_point_directory "$setSubDir" fi if [ -n "$setFullSkips" ];then set_skip_data "$setFullSkips" fi if [ -n "$setFullAdds" ];then set_add_data "$setFullAdds" fi if [ -n "$setCloneData" ];then set_clone_data "$setCloneData" fi if [ -n "$setMount" ];then set_mount_data "$setMount" fi if [ -n "$setEmailer" ];then set_emailer_data "$setEmailer" fi if [ -n "$setPrePost" ];then set_pre_post_data "$setPrePost" fi } #### ------------------------------------------------------------------- #### Error Handling #### ------------------------------------------------------------------- # Error handling # args: $1 - error number; $2 - optional, extra information error_handler() { local error_message='' errorType='' extra2='' extra3='' cleanedMessage='' case $1 in 50) errorType="Event" W=${M} ;; *) errorType="Error" ;; esac # assemble the error message case $1 in 2) error_message="The component: ${C}MOUNT_BU_DISK${W} failed to successfully complete its task. Error code was: ${C}$2" ;; 3) error_message="The component: ${C}UNMOUNT_BU_DISK${W} failed to successfully complete its task. Error code was: ${C}$2" ;; 4) error_message="You must be logged in as ${C}root${W} to run this script." ;; 5) error_message="dependency not met: ${C}$2${W} not found in path" ;; 6) error_message="Your backup partition/directory ${C}$BACKUP_MOUNT_POINT${W} is not present.\nPlease make sure to create it or mount it up before you proceed." ;; 7) error_message="One of the options you entered in your script parameters: ${C}$2${W}\nIs not supported, or requires a further argument.\nFor a list of supported options, check the help menu: ${C}$SELF_NAME -h" ;; 8) error_message="the self-updater failed, wget exited with error: ${C}$2${W}.\nYou probably need to be root.\nHint, to make for easy updates without being root, do: chown ${C}$SELF_PATH/$SELF_NAME" ;; 9) error_message="unset" ;; 10) error_message="the alt download url you provided: ${C}$2${W}\nappears to be wrong, download aborted. Please note, the url\nneeds to end in ${C}/${W}, without ${C}$SELF_NAME${W}, like: ${C}http://yoursite.com/downloads/" ;; 11) error_message="unsupported testing option argument: ${C}-! $2" ;; 12) error_message="the svn branch download url: ${C}$2${W}\nappears to be empty currently. Make sure there is an actual svn branch version\nactive before you try this again. Check http://code.google.com/p/inxi\nto verify the branch status." ;; 13) error_message="The option argument you gave is not supported: ${C}$2" ;; 14) error_message="You do not have the required backup application installed. Missing: ${C}$2" ;; 15) error_message="You cannot use both ${C}-c${W} and ${C}-d${W}, only one or the other. Either you are clearing, or deleting." ;; 16) error_message="${C}B_VARIABLES_SET='false'${W} in the file ${C}rbxi-data/$SELF_VALUES${W} must be set to ${C}'true' before you can run $SELF_NAME\nYou must configure that file first, then when you're done, you can the script." ;; 17) error_message="The backup job you selected (${C}$2${W}) is empty. Please make sure you entered the right number." ;; 18) error_message="The backup directory you selected (${C}$2${W}) is empty.\nYou cannot backup to, or mount, a blank directory." ;; 19) error_message="Your backup program ${C}$BACKUP_APP${W} does not support the -C clone option." ;; 20) error_message="The backup source directory: ${C}$2${W} does not exist. Unable to continue." ;; 21) error_message="You are using an unsupported color scheme: ${C}$2" ;; 22) error_message="Could not load user values file: ${C}$SELF_DATA_DIR$SELF_VALUES${W}\nPlease double check that the file exists and is in: ${C}$SELF_DATA_DIR${W}\nExiting now." ;; 23) error_message="Unable to locate the script data directory: ${C}$SELF_PATH$SELF_DATA\n${C}rbxi${W} requires the program ${C}$2${W} to create its paths if you start using a symbolic link.\nYou must install this application before you can run ${C}$SELF_NAME${W} with a sybolic link.\nUnable to continue." ;; 24) error_message="Your backup destination directory: ${C}$2${W}\ndoes not seem to exist. Please check your settings and make sure the directory\nyou are using actually exists." ;; 25) error_message="Your backup application ${C}$BACKUP_APP${W} exited with error: ${C}$2${W}\nPlease check the source of the error and try again. Exiting $SELF_NAME now." ;; 26) error_message="The variable ${C}BACKUP_MOUNT_POINT${W} is empty. Backup directory mount cannnot continue." ;; 27) error_message="The function: ${C}pre_mount_tasks${W} exited with error code: (${C}$2${W})" ;; 28) error_message="The function: ${C}post_mount_tasks${W} exited with error code: (${C}$2${W})" ;; 29) error_message="The function: ${C}post_umount_tasks${W} exited with error code: (${C}$2${W})" ;; 30) error_message="The rbxi log directory ${C}$2${W} does not exist.\nPlease correct the path in rbxi-values LOGFILE_DIR='' before continuing." ;; 31) error_message="User set Action returned error: $2" ;; 32) error_message="No console browser detected in your system. Requires one of these: links2 elinks w3m links lynx" ;; 50) error_message="User initiated script termination. Exiting $SELF_NAME now." ;; 100) error_message="$SELF_NAME does not yet support the backup app you requested: ${C}$2${W}\nThis support should be coming sometime soon.\nCurrently supported backup applications are: rdiff-backup." umount_backup_disk ;; *) error_message="Unknown error number: ${C}$1" ;; esac log_function_data 'error' "$errorType ($1)\n$error_message" run_emailer_tasks 'error' "$errorType ($1)\n$error_message" # then print it and exit echo -e "${W}$errorType ${C}$1${W}: $error_message${N}" exit $1 } # args: $1 type: start/error/data; $2 - data to be logged log_function_data() { if [ "$B_LOGGING" == 'true' ];then local data=$( echo -e "$2" | sed 's/\x1b\[[0-9]\{1,2\}\(;[0-9]\{1,2\}\)\{0,2\}m//g' ) local actionTime=$( date +"%R:%S" ) local logFile=${LOGFILE_DIR}${SELF_NAME}.log # check user error first if [ ! -d $LOGFILE_DIR ];then error_handler 30 "$LOGFILE_DIR" fi # I don't to try to handle various distro logrotate tools, so I'm making my own here # going to rotate it at 100kB if [ -f $logFile ];then # this shouldn't have been necessary, but if on same line as -f test, gives error # if no file exists. if [ "$( du -s $logFile | awk '{print $1}' )" -gt $LOGFILE_SIZE ];then mv -f $logFile ${LOGFILE_DIR}${SELF_NAME}.1.log fi fi # then make sure the file is ready to go if [ ! -f $logFile ];then touch $logFile fi case $1 in start) echo $BA >> $logFile echo "Starting $SELF_NAME at: $( date +"%Y %B %e - %R:%S" )" >> $logFile echo "Script start options: $2" >> $logFile echo $LI >> $logFile if [ -f $SELF_CONFIGS -a -n "$( cat $SELF_CONFIGS )" ];then echo "Previous Script Config Data:" >> $logFile echo "$( cat $SELF_CONFIGS )" >> $logFile else echo "Previous Script Config Data File Is Null." >> $logFile fi echo $LI >> $logFile echo "Starting backup job." >> $logFile ;; error|data) echo -e "$actionTime: $data" >> $logFile ;; esac fi } #### ------------------------------------------------------------------- #### Utilities #### ------------------------------------------------------------------- # set global color variables # options: 0 - no colors; 1 - defaults; 2 light bkgd, fancy; dark background, simple # 4 dark background, fancy; 4 smxi set_self_colors() { # set colors # ="" # black background case "$COLOR_SCHEME" in # colors off 0) W='' # Warning message E='' # script Error S='' # Standard message Q='' # Questions M='' # Message C='' # Command or Path N='' # default system console color: Normal :: make last in colors ;; # default, either dark or light background ''|1) W="" # Warning message E="" # script Error S="" # Standard message Q="" # Questions M="" # Message C="" # Command or Path B="" # black background N="" # default system console color: Normal ;; # light background, fancy 2) W="" # Warning message E="" # script Error S="" # Standard message Q="" # Questions M="" # Message C="" # Command or Path B="" # black background N="" # default system console color: Normal :: make last in colors ;; # dark background, simple 3) W="" # Warning message E="" # script Error S="" # Standard message Q="" # Questions M="" # Message C="" # Command or Path B="" # black background N="" # default system console color: Normal ;; # dark background, fancy 4) W="" # Warning message E="" # script Error S="" # Standard message Q="" # Questions M="" # Message C="" # Command or Path B="" # black background N="" # default system console color: Normal :: make last in colors ;; # dark background, smxi style 5) W="" # red: Warning message E="" # yellow: script Error S="" # green: Standard message Q="" # CYAN: Questions M="" # CYAN: Message C="" # MAGENTA: Command or Path B="" # BLUE: Message N="" # default system console color: Normal :: make last in colors ;; *) error_handler 21 "$COLOR_SCHEME" ;; esac # script layout stuff BAR=${S}$BA${N} EBAR=${E}$BA${N} WBAR=${W}$BA${N} MBAR=${M}$BA${N} LINE=${S}$LI${N} ELINE=${E}$LI${N} MLINE=${M}$LI${N} WLINE=${W}$LI${N} SPACER=' ' } create_symbolic_link() { local ulbLink="/usr/local/bin/$SELF_NAME" local scriptInPath=$( which $SELF_NAME | grep -v "./$SELF_NAME" ) if [ ! -L $ulbLink -a ! -f $ulbLink -a -z "$scriptInPath" ];then check_is_root # only do the linking if the path is real if type $LSOF &>/dev/null;then echo "${S}Creating link now...${N}" ln -s $SELF_PATH/$SELF_NAME $ulbLink else echo "${C}$SELF_PATH ${W}is not properly set, cannot automatically create symbolic link.${N}" fi else echo "${M}$SELF_NAME is already in your system path, or a link to it already exists.${N}" fi } # args: $1 - main/v print_history_data() { local lastBackupDirectory='Unset' local lastBackupDate='Unset' local lastBackupDuration='Unset' local lastBackupApp='Unset' local lastBackupJobNu='Unset' local rdbuHistoryHolder='' local rsyncHistoryHolder='' local rdbuHistory='Unset' local rsyncHistory='Unset' local rdbuHistory2='' local rsyncHistory2='' if [ "$1" != 'main' ];then M='' C='' N='' S='' fi if [ -f $SELF_CONFIGS ];then lastBackupDirectory=$( grep 'last-backup-directory=' $SELF_CONFIGS | cut -d '=' -f 2 ) lastBackupDate=$( grep 'last-backup-date=' $SELF_CONFIGS | cut -d '=' -f 2 ) lastBackupDuration=$( grep 'last-backup-duration=' $SELF_CONFIGS | cut -d '=' -f 2 ) lastBackupApp=$( grep 'last-backup-app=' $SELF_CONFIGS | cut -d '=' -f 2 ) lastBackupJobNu=$( grep 'last-backup-job=' $SELF_CONFIGS | cut -d '=' -f 2 ) # add line breaks because output is too long for single line rdbuHistoryHolder="$( grep 'rdbu-backup-history=' $SELF_CONFIGS | cut -d '=' -f 2 )" rsyncHistoryHolder="$( grep 'rsync-backup-history=' $SELF_CONFIGS | cut -d '=' -f 2 )" rdbuHistory="$( cut -d '~' -f 1 <<< $rdbuHistoryHolder )" rsyncHistory="$( cut -d '~' -f 1 <<< $rsyncHistoryHolder )" if [ -n "$( grep '~' <<< $rdbuHistoryHolder )" ];then rdbuHistory2="$( cut -d '~' -f 2 <<< $rdbuHistoryHolder )" rdbuHistory2='echo " ${C}'$rdbuHistory2'${N}"' fi if [ -n "$( grep '~' <<< $rsyncHistoryHolder )" ];then rsyncHistory2="$( cut -d '~' -f 2 <<< $rsyncHistoryHolder )" rsyncHistory2='echo " ${C}'$rsyncHistory2'${N}"' fi fi echo "${M}Last Backup Date: ${C}$lastBackupDate${N}" echo "${M}Last Backup Directory: ${C}$lastBackupDirectory${N}" echo "${M}Last Backup Program: ${C}$lastBackupApp${N}" if [ "$lastBackupJobNu" == 'none' ];then echo "${M}Your last backup did not use the ${C}Job${M} feature.${N}" else echo "${M}Last Backup Job Number: ${C}$lastBackupJobNu${N}" fi if [ "$1" == 'main' ];then case "$BACKUP_APP" in rdiff-backup) echo "${M}Rdiff-backup history: ${C}$rdbuHistory${N}" eval "$rdbuHistory2" ;; rsync) echo "${M}Rsync backup history: ${C}$rsyncHistory${N}" eval "$rsyncHistory2" ;; esac else echo "${M}Rdiff-backup history: ${C}$rdbuHistory${N}" eval "$rdbuHistory2" echo "${M}Rsync backup history: ${C}$rsyncHistory${N}" eval "$rsyncHistory2" fi } ## print out version information for -v print_version_info() { local last_modified=$( grep -im 1 'date:' $SELF_PATH/$SELF_NAME | awk '{print $3,$4,$5}' ) local versionRemote='' versionRemoteDate='' versionRemoteNumber='' remoteNotify='' if [ "$B_UPDATE_NOTIFIER" == 'true' ];then versionRemote=$( check_remote_version ) versionRemoteDate=$( cut -d ':' -f 2 <<< $versionRemote ) versionRemoteNumber=$( cut -d ':' -f 1 <<< $versionRemote ) if [ "$versionRemoteNumber" != "$SELF_VERSION_NUMBER" ];then remoteNotify='echo " ${M}(Newer version available: ${C}$versionRemoteNumber${M} Release Date: ${C}$versionRemoteDate${M})${N}"' fi fi if [ "$1" == 'opt' ];then echo $LINE echo "$SELF_NAME - the universal, portable, system backup script." echo "Version: $SELF_VERSION_NUMBER" echo "Script Last Modified: $last_modified" echo "Script Location: $SELF_PATH${N}" print_history_data elif [ "$1" == 'main' ];then echo " ${C}$SELF_NAME${S} ${M}:: Version: ${C}$SELF_VERSION_NUMBER${S} ${M}:: Released: ${C}$last_modified${N}" eval "$remoteNotify" fi } # args: $1 - download url, not including file name; $2 - string to print out # note that $1 must end in / to properly construct the url path self_updater() { local wget_error=0 local ua='-U s-tools/rbxi.updater' echo "Starting $SELF_NAME self updater." echo "Currently running $SELF_NAME version number: $SELF_VERSION_NUMBER" echo "Updating $SELF_NAME in $SELF_PATH using $2 as download source..." # first test if path is good, need to make sure it's good because we're -O overwriting file # remove -q for testing wget --spider $1$SELF_NAME || wget_error=$? # then do the actual download if [[ $wget_error -eq 0 ]];then wget $ua -O $SELF_PATH/$SELF_NAME $1$SELF_NAME || wget_error=$? if [[ $wget_error -eq 0 ]];then SELF_VERSION_NUMBER=$( grep -im 1 'version:' $SELF_PATH/$SELF_NAME | awk '{print $3}' ) echo "Successfully updated to $2 version: $SELF_VERSION_NUMBER" echo "To run the new version, just start $SELF_NAME again." exit 0 fi fi # now run the error handlers on any wget failure if [[ $wget_error -gt 0 ]];then if [[ $2 == 'git server' ]];then error_handler 8 "$wget_error" elif [[ $2 == 'alt server' ]];then error_handler 10 "$1" else error_handler 12 "$1" fi fi } show_self_readme() { local browser='' browser_path='' for browser in $CONSOLE_BROWSER links2 elinks w3m links lynx do if [ -n "$( which $browser )" ];then browser_path=$( which $browser ) break fi done if [ -n "$browser_path" ];then $browser_path $SELF_PATH$SELF_DATA$SELF_README else error_handler 32 fi } # creates the spinning wheel if script starts with -s option, and shows completion spinning_wheel_activity_indicator() { local completionText='' if [ "$1" == 'delete' ];then completionText='backup directories removed' fi if [ "$1" == 'backup' ];then completionText="$2 backed up" fi echo -n ${S} # while kill -0 $GET_PID while [ -e /proc/$GET_PID ] do sleep $SLEEP_TIME_SPINNER echo -n '|' echo -ne "\b" sleep $SLEEP_TIME_SPINNER echo -n '/' echo -ne "\b" sleep $SLEEP_TIME_SPINNER echo -n '-' echo -ne "\b" sleep $SLEEP_TIME_SPINNER echo -n "\\" echo -ne "\b" done echo -ne "\b $completionText" echo ${N} } # args: $1 umount/ trap_handler() { local i='' case "$1" in umount) echo echo "${S}You are leaving $SELF_NAME with the backup partition still mounted!" echo "Running sync to make sure writes to drives are done (can take a while)...${N}" sync # give the disk time sync its writes before umount... # set in rbxi-values if you need to increase or decrease the time for premature # or forced script exit for umount operation to work successfully. echo "Waiting a few seconds to let thihgs settle before exiting...${N}" for (( i=0; i < $SLEEP_TIME_UMOUNT; i++ )) do echo -n "${M}...tick${N}" sleep $i done echo "${M}...done!${N}" umount_backup_disk run_pre_post_tasks 'post-umount' # set trap to null to avoid loops for final exits trap - INT TERM EXIT error_handler 50 ;; esac } #### ------------------------------------------------------------------- #### basic tests #### ------------------------------------------------------------------- # this will load/test anything that is required check_self_requires() { # this test handles three cases: # 1: constructing a path with possibly user hard-coded value for SELF_PATH fails # 2: constructing the path with dirname and rbxi-data fails to detect a directory # 3: lsof does not exit in system if [ ! -d "$SELF_PATH$SELF_DATA" ] && [ ! -d "$( dirname $0 )$SELF_DATA" ] && ! type $LSOF &>/dev/null;then error_handler 23 'lsof' fi ## add in user variable values, sticky value file if [ ! -f "$SELF_DATA_DIR$SELF_VALUES" ];then error_handler 22 fi } check_is_root() { if [ "$( whoami )" != "root" ];then error_handler 4 fi } check_startup_stuff() { check_is_root create_etc_configs check_bu_app_installed if [ "$B_CLEAN_OLDER" == 'true' -a "$B_DELETE_BACKUP" == 'true' ];then error_handler 15 fi if [ "$B_VARIABLES_SET" != 'true' ];then error_handler 16 fi if [ "$B_IS_CLONE" == 'true' -a "$BACKUP_APP" != 'rsync' ];then error_handler 19 fi } check_self_path() { local ExDir=$( dirname $0 ) if [ "$( pwd )" != "$ExDir" -a "$ExDir" != '.' ];then cd $ExDir fi } check_self_changes() { local oldBuMount='BACKUP_DIRECTORY' local oldBuMountSub='BACKUP_SUB_DIR' local updateBuMount=$( egrep "($oldBuMount|$oldBuMountSub)" $SELF_DATA_DIR$SELF_VALUES $SELF_DATA_DIR$SELF_README ) if [ -n "$updateBuMount" ];then echo "${S}Updating your $SELF_VALUES $SELF_README files to use new variable names:" echo "BACKUP_MOUNT_POINT replaces BACKUP_DIRECTORY" echo "BACKUP_MOUNT_POINT_DIRECTORY replaces BACKUP_SUB_DIR" echo "Please restart $SELF_NAME after this is completed.${N}" sed -i 's/BACKUP_DIRECTORY/BACKUP_MOUNT_POINT/g' $SELF_DATA_DIR$SELF_VALUES $SELF_DATA_DIR$SELF_README sed -i 's/BACKUP_SUB_DIR/BACKUP_MOUNT_POINT_DIRECTORY/g' $SELF_DATA_DIR$SELF_VALUES $SELF_DATA_DIR$SELF_README sed -i 's/2\.5\.[0-1]/2.5.2/g' $SELF_DATA_DIR$SELF_VALUES $SELF_DATA_DIR$SELF_README echo "${S}Updated and exiting. Please restart $SELF_NAME, sorry for the inconvenience.${N}" exit 0 fi } check_bu_app_installed() { local pathExists='' appToCheck='' # this must set error to /dev/null to avoid false positive in some cases local appWhich="$( which $BACKUP_APP )" # more handling is required for cron jobs, which might not show which output case $BACKUP_APP in rdiff-backup) appToCheck=$RDIFF_PATH ;; rsync) appToCheck=$RSYNC_PATH ;; esac # checking the actual paths here, not relying on unreliable which output if [ ! -x "$appWhich" -a ! -x $appToCheck ];then error_handler 14 $BACKUP_APP fi } # check to see if its' a local or remote directory # args: $1 - directory path, check for :/ or @ check_directory_remote() { local isRemote=$( grep -E '(:/)' <<< "$1" ) if [ -d "$1" -o -n "$isRemote" ];then return 0 else return 1 fi } # args: $1 - directory full path to check check_backup_source_directory() { check_directory_remote "$1" local returnIs="$?" echo -n "${S}Checking backup source ${C}$1${S}....${N}" if [ "$returnIs" -eq 0 ];then echo "${S}....${M}valid${N}" else echo "${S}....${W}INVALID${N}" error_handler 20 "$1" fi } # args: $1 - backup destination local directory check_backup_destination_directory() { check_directory_remote "$1" local returnIs="$?" echo -n "${S}Checking backup destination ${C}$1${S}....${N}" if [ "$returnIs" -eq 0 ];then echo "${S}....${M}valid${N}" else echo "${S}....${W}INVALID${N}" error_handler 24 "$1" fi } check_remote_version() { local versionRemote='' local ua='-U s-tools/rbxi.rb-version' # get ip using wget redirect to stdout. This is a clean, text only IP output url. versionRemote=$( wget $ua -q -O - http://smxi.org/rb/rb-version | grep 'rbxi=' | cut -d '=' -f 2 ) echo "$versionRemote" } create_etc_configs() { if [ ! -f $SELF_CONFIGS ];then touch $SELF_CONFIGS echo 'last-backup-directory=Unset' >> $SELF_CONFIGS echo 'last-backup-date=Unset' >> $SELF_CONFIGS echo 'last-backup-duration=Unset' >> $SELF_CONFIGS fi if [ -z "$( grep 'rdbu-backup-history=' $SELF_CONFIGS )" ];then echo 'rdbu-backup-history=Unset' >> $SELF_CONFIGS fi if [ -z "$( grep 'rsync-backup-history=' $SELF_CONFIGS )" ];then echo 'rsync-backup-history=Unset' >> $SELF_CONFIGS fi if [ -z "$( grep 'last-backup-app=' $SELF_CONFIGS )" ];then echo 'last-backup-app=Unset' >> $SELF_CONFIGS fi if [ -z "$( grep 'last-backup-job=' $SELF_CONFIGS )" ];then echo 'last-backup-job=Unset' >> $SELF_CONFIGS fi } #### ------------------------------------------------------------------- #### set data functions - primary, directory, backup commands, mount #### ------------------------------------------------------------------- # load proper values for locations and command strings set_primary_backup_data() { case "$BACKUP_APP" in rsync) # update global file names. # First make sure no user error with the directory name occured with options if [ -z "$BACKUP_MOUNT_POINT_RS" ];then error_handler 18 'BACKUP_MOUNT_POINT_RS' fi # then remove this data, since we only use the primary directories if [ "$B_IS_CLONE" == 'true' ];then BACKUP_MOUNT_POINT_DIRECTORY_RS='' fi # note: these values were set in set_backup_mount_point # and set_backup_mount_point_directory if -B or -D were used # note: this is required for mounts BACKUP_MOUNT_POINT=$BACKUP_MOUNT_POINT_RS BACKUP_LOCATION=$BACKUP_MOUNT_POINT_RS$BACKUP_MOUNT_POINT_DIRECTORY_RS EXCLUDE_ROOT=$EXCLUDE_ROOT_RS EXCLUDE_HOME=$EXCLUDE_HOME_RS EXCLUDE_DATA_1=$EXCLUDE_DATA_1_RS EXCLUDE_DATA_2=$EXCLUDE_DATA_2_RS EXCLUDE_DATA_3=$EXCLUDE_DATA_3_RS EXCLUDE_DATA_4=$EXCLUDE_DATA_4_RS EXCLUDE_DATA_5=$EXCLUDE_DATA_5_RS EXCLUDE_DATA_6=$EXCLUDE_DATA_6_RS EXCLUDE_DATA_7=$EXCLUDE_DATA_7_RS EXCLUDE_DATA_8=$EXCLUDE_DATA_8_RS EXCLUDE_DATA_9=$EXCLUDE_DATA_9_RS EXCLUDE_DATA_10=$EXCLUDE_DATA_10_RS ;; rdiff-backup) # First make sure no user error with the directory name occured with options if [ -z "$BACKUP_MOUNT_POINT" ];then error_handler 18 'BACKUP_MOUNT_POINT' fi BACKUP_LOCATION=$BACKUP_MOUNT_POINT$BACKUP_MOUNT_POINT_DIRECTORY ;; esac if [ -z "$BACKUP_LOCATION" ];then error_handler 19 fi check_backup_destination_directory "$BACKUP_MOUNT_POINT" } # these will be tested in the actual backup function for exist if local, or # if have remote path syntax. rsync/rdiff will handle bad paths for remote # destination directories. # create backup directory then set backup directory names set_backup_destination_data() { local month=$( date +%m ) # assemble the backup paths, if they are clones sub directory can be null HOME_BACKUP=$( set_backup_destination_path "$BACKUP_LOCATION" "$HOME_DIR" ) ROOT_BACKUP=$( set_backup_destination_path "$BACKUP_LOCATION" "$ROOT_DIR" ) DATA_1_BACKUP=$( set_backup_destination_path "$BACKUP_LOCATION" "$DATA_1_DIR" ) DATA_2_BACKUP=$( set_backup_destination_path "$BACKUP_LOCATION" "$DATA_2_DIR" ) DATA_3_BACKUP=$( set_backup_destination_path "$BACKUP_LOCATION" "$DATA_3_DIR" ) DATA_4_BACKUP=$( set_backup_destination_path "$BACKUP_LOCATION" "$DATA_4_DIR" ) DATA_5_BACKUP=$( set_backup_destination_path "$BACKUP_LOCATION" "$DATA_5_DIR" ) DATA_6_BACKUP=$( set_backup_destination_path "$BACKUP_LOCATION" "$DATA_6_DIR" ) DATA_7_BACKUP=$( set_backup_destination_path "$BACKUP_LOCATION" "$DATA_7_DIR" ) DATA_8_BACKUP=$( set_backup_destination_path "$BACKUP_LOCATION" "$DATA_8_DIR" ) DATA_9_BACKUP=$( set_backup_destination_path "$BACKUP_LOCATION" "$DATA_9_DIR" ) DATA_10_BACKUP=$( set_backup_destination_path "$BACKUP_LOCATION" "$DATA_10_DIR" ) } # This makes sure that ending slashes do not occur in backup directory paths. # args: $1 - $BACKUP_LOCATION; $2 - backup subdirectory. If null, use just use $1 set_backup_destination_path() { local backupPath=$1 if [ -n "$2" ];then backupPath="$backupPath/$2" fi echo $backupPath } set_backup_commands() { local dryRun='' options='' case "$BACKUP_APP" in rsync) if [ "$B_CLEAN_OLDER" == 'true' ];then RSYNC_DELETE=' --delete --delete-excluded ' fi if [ "$B_DRY_RUN" == 'true' ];then dryRun=' --dry-run ' fi # set commands # note: extra options must END with ssh connection string # NOTE: -a = -rlptgoD # --acls only if needed options=" --hard-links --xattrs --sparse --numeric-ids --times -a $dryRun $RSYNC_DELETE $RSYNC_EXTRA_OPTIONS" HOME_BU_COMMAND="$RSYNC_PATH --exclude-from=$SELF_DATA_DIR$EXCLUDE_HOME $options $HOME_PATH $HOME_BACKUP" ROOT_BU_COMMAND="$RSYNC_PATH --exclude-from=$SELF_DATA_DIR$EXCLUDE_ROOT $options $ROOT_PATH $ROOT_BACKUP" DATA_1_BU_COMMAND="$RSYNC_PATH --exclude-from=$SELF_DATA_DIR$EXCLUDE_DATA_1 $options $DATA_1_PATH $DATA_1_BACKUP" DATA_2_BU_COMMAND="$RSYNC_PATH --exclude-from=$SELF_DATA_DIR$EXCLUDE_DATA_2 $options $DATA_2_PATH $DATA_2_BACKUP" DATA_3_BU_COMMAND="$RSYNC_PATH --exclude-from=$SELF_DATA_DIR$EXCLUDE_DATA_3 $options $DATA_3_PATH $DATA_3_BACKUP" DATA_4_BU_COMMAND="$RSYNC_PATH --exclude-from=$SELF_DATA_DIR$EXCLUDE_DATA_4 $options $DATA_4_PATH $DATA_4_BACKUP" DATA_5_BU_COMMAND="$RSYNC_PATH --exclude-from=$SELF_DATA_DIR$EXCLUDE_DATA_5 $options $DATA_5_PATH $DATA_5_BACKUP" DATA_6_BU_COMMAND="$RSYNC_PATH --exclude-from=$SELF_DATA_DIR$EXCLUDE_DATA_6 $options $DATA_6_PATH $DATA_6_BACKUP" DATA_7_BU_COMMAND="$RSYNC_PATH --exclude-from=$SELF_DATA_DIR$EXCLUDE_DATA_7 $options $DATA_7_PATH $DATA_7_BACKUP" DATA_8_BU_COMMAND="$RSYNC_PATH --exclude-from=$SELF_DATA_DIR$EXCLUDE_DATA_8 $options $DATA_8_PATH $DATA_8_BACKUP" DATA_9_BU_COMMAND="$RSYNC_PATH --exclude-from=$SELF_DATA_DIR$EXCLUDE_DATA_9 $options $DATA_9_PATH $DATA_9_BACKUP" DATA_10_BU_COMMAND="$RSYNC_PATH --exclude-from=$SELF_DATA_DIR$EXCLUDE_DATA_10 $options $DATA_10_PATH $DATA_10_BACKUP" # set text BACKUP_CLEAR='Backing up' # reset to false so main backup function can finish up B_CLEAN_OLDER='false' ;; rdiff-backup) # set commands # http://www.mail-archive.com/rdiff-backup-users@nongnu.org/msg01212.html # --exclude-sockets to get rid of that dumb socket error if [ "$B_CLEAN_OLDER" != 'true' ];then # set commands options=" --exclude-sockets $RDIFF_EXTRA_OPTIONS " HOME_BU_COMMAND="$RDIFF_PATH $options --exclude-globbing-filelist $SELF_DATA_DIR$EXCLUDE_HOME $HOME_PATH $HOME_BACKUP" ROOT_BU_COMMAND="$RDIFF_PATH $options --exclude-globbing-filelist $SELF_DATA_DIR$EXCLUDE_ROOT $ROOT_PATH $ROOT_BACKUP" DATA_1_BU_COMMAND="$RDIFF_PATH $options --exclude-globbing-filelist $SELF_DATA_DIR$EXCLUDE_DATA_1 $DATA_1_PATH $DATA_1_BACKUP" DATA_2_BU_COMMAND="$RDIFF_PATH $options --exclude-globbing-filelist $SELF_DATA_DIR$EXCLUDE_DATA_2 $DATA_2_PATH $DATA_2_BACKUP" DATA_3_BU_COMMAND="$RDIFF_PATH $options --exclude-globbing-filelist $SELF_DATA_DIR$EXCLUDE_DATA_3 $DATA_3_PATH $DATA_3_BACKUP" DATA_4_BU_COMMAND="$RDIFF_PATH $options --exclude-globbing-filelist $SELF_DATA_DIR$EXCLUDE_DATA_4 $DATA_4_PATH $DATA_4_BACKUP" DATA_5_BU_COMMAND="$RDIFF_PATH $options --exclude-globbing-filelist $SELF_DATA_DIR$EXCLUDE_DATA_5 $DATA_5_PATH $DATA_5_BACKUP" DATA_6_BU_COMMAND="$RDIFF_PATH $options --exclude-globbing-filelist $SELF_DATA_DIR$EXCLUDE_DATA_6 $DATA_6_PATH $DATA_6_BACKUP" DATA_7_BU_COMMAND="$RDIFF_PATH $options --exclude-globbing-filelist $SELF_DATA_DIR$EXCLUDE_DATA_7 $DATA_7_PATH $DATA_7_BACKUP" DATA_8_BU_COMMAND="$RDIFF_PATH $options --exclude-globbing-filelist $SELF_DATA_DIR$EXCLUDE_DATA_8 $DATA_8_PATH $DATA_8_BACKUP" DATA_9_BU_COMMAND="$RDIFF_PATH $options --exclude-globbing-filelist $SELF_DATA_DIR$EXCLUDE_DATA_9 $DATA_9_PATH $DATA_9_BACKUP" DATA_10_BU_COMMAND="$RDIFF_PATH $options --exclude-globbing-filelist $SELF_DATA_DIR$EXCLUDE_DATA_10 $DATA_10_PATH $DATA_10_BACKUP" # set text BACKUP_CLEAR='Backing up' else # set commands options=" --force --remove-older-than $RDIFF_REMOVE_TIME " HOME_BU_COMMAND="$RDIFF_PATH $options $HOME_BACKUP" ROOT_BU_COMMAND="$RDIFF_PATH $options $RDIFF_REMOVE_TIME $ROOT_BACKUP" DATA_1_BU_COMMAND="$RDIFF_PATH $options $DATA_1_BACKUP" DATA_2_BU_COMMAND="$RDIFF_PATH $options $DATA_2_BACKUP" DATA_3_BU_COMMAND="$RDIFF_PATH $options $DATA_3_BACKUP" DATA_4_BU_COMMAND="$RDIFF_PATH $options $DATA_4_BACKUP" DATA_5_BU_COMMAND="$RDIFF_PATH $options $DATA_5_BACKUP" DATA_6_BU_COMMAND="$RDIFF_PATH $options $DATA_6_BACKUP" DATA_7_BU_COMMAND="$RDIFF_PATH $options $DATA_7_BACKUP" DATA_8_BU_COMMAND="$RDIFF_PATH $options $DATA_8_BACKUP" DATA_9_BU_COMMAND="$RDIFF_PATH $options $DATA_9_BACKUP" DATA_10_BU_COMMAND="$RDIFF_PATH $options $DATA_10_BACKUP" # set text BACKUP_CLEAR="Removing all increments older than $RDIFF_REMOVE_TIME from" fi ;; esac } # all error null directory handling is done in the final set_primary_backup_data function # args: $1 - backup directory number set_backup_mount_point() { case $1 in 1) BACKUP_MOUNT_POINT=$BACKUP_MOUNT_POINT_1 BACKUP_MOUNT_POINT_RS=$BACKUP_MOUNT_POINT_1_RS ;; 2) BACKUP_MOUNT_POINT=$BACKUP_MOUNT_POINT_2 BACKUP_MOUNT_POINT_RS=$BACKUP_MOUNT_POINT_2_RS ;; 3) BACKUP_MOUNT_POINT=$BACKUP_MOUNT_POINT_3 BACKUP_MOUNT_POINT_RS=$BACKUP_MOUNT_POINT_3_RS ;; 4) BACKUP_MOUNT_POINT=$BACKUP_MOUNT_POINT_4 BACKUP_MOUNT_POINT_RS=$BACKUP_MOUNT_POINT_4_RS ;; 5) BACKUP_MOUNT_POINT=$BACKUP_MOUNT_POINT_5 BACKUP_MOUNT_POINT_RS=$BACKUP_MOUNT_POINT_5_RS ;; 6) BACKUP_MOUNT_POINT=$BACKUP_MOUNT_POINT_6 BACKUP_MOUNT_POINT_RS=$BACKUP_MOUNT_POINT_6_RS ;; 7) BACKUP_MOUNT_POINT=$BACKUP_MOUNT_POINT_7 BACKUP_MOUNT_POINT_RS=$BACKUP_MOUNT_POINT_7_RS ;; 8) BACKUP_MOUNT_POINT=$BACKUP_MOUNT_POINT_8 BACKUP_MOUNT_POINT_RS=$BACKUP_MOUNT_POINT_8_RS ;; 9) BACKUP_MOUNT_POINT=$BACKUP_MOUNT_POINT_9 BACKUP_MOUNT_POINT_RS=$BACKUP_MOUNT_POINT_9_RS ;; 10) BACKUP_MOUNT_POINT=$BACKUP_MOUNT_POINT_10 BACKUP_MOUNT_POINT_RS=$BACKUP_MOUNT_POINT_10_RS ;; esac } # args: $1 - backup directory number set_backup_mount_point_directory() { case $1 in 1) BACKUP_MOUNT_POINT_DIRECTORY=$BACKUP_MOUNT_POINT_DIRECTORY_1 BACKUP_MOUNT_POINT_DIRECTORY_RS=$BACKUP_MOUNT_POINT_DIRECTORY_1_RS ;; 2) BACKUP_MOUNT_POINT_DIRECTORY=$BACKUP_MOUNT_POINT_DIRECTORY_2 BACKUP_MOUNT_POINT_DIRECTORY_RS=$BACKUP_MOUNT_POINT_DIRECTORY_2_RS ;; 3) BACKUP_MOUNT_POINT_DIRECTORY=$BACKUP_MOUNT_POINT_DIRECTORY_3 BACKUP_MOUNT_POINT_DIRECTORY_RS=$BACKUP_MOUNT_POINT_DIRECTORY_3_RS ;; 4) BACKUP_MOUNT_POINT_DIRECTORY=$BACKUP_MOUNT_POINT_DIRECTORY_4 BACKUP_MOUNT_POINT_DIRECTORY_RS=$BACKUP_MOUNT_POINT_DIRECTORY_4_RS ;; 5) BACKUP_MOUNT_POINT_DIRECTORY=$BACKUP_MOUNT_POINT_DIRECTORY_5 BACKUP_MOUNT_POINT_DIRECTORY_RS=$BACKUP_MOUNT_POINT_DIRECTORY_5_RS ;; 6) BACKUP_MOUNT_POINT_DIRECTORY=$BACKUP_MOUNT_POINT_DIRECTORY_6 BACKUP_MOUNT_POINT_DIRECTORY_RS=$BACKUP_MOUNT_POINT_DIRECTORY_6_RS ;; 7) BACKUP_MOUNT_POINT_DIRECTORY=$BACKUP_MOUNT_POINT_DIRECTORY_7 BACKUP_MOUNT_POINT_DIRECTORY_RS=$BACKUP_MOUNT_POINT_DIRECTORY_7_RS ;; 8) BACKUP_MOUNT_POINT_DIRECTORY=$BACKUP_MOUNT_POINT_DIRECTORY_8 BACKUP_MOUNT_POINT_DIRECTORY_RS=$BACKUP_MOUNT_POINT_DIRECTORY_8_RS ;; 9) BACKUP_MOUNT_POINT_DIRECTORY=$BACKUP_MOUNT_POINT_DIRECTORY_9 BACKUP_MOUNT_POINT_DIRECTORY_RS=$BACKUP_MOUNT_POINT_DIRECTORY_9_RS ;; 10) BACKUP_MOUNT_POINT_DIRECTORY=$BACKUP_MOUNT_POINT_DIRECTORY_10 BACKUP_MOUNT_POINT_DIRECTORY_RS=$BACKUP_MOUNT_POINT_DIRECTORY_10_RS ;; esac } # args: $1 - data in format: x:y:z where x/y/z are null or 1-5 set_emailer_data(){ local emailStart=$( cut -d ':' -f 1 <<< $1 ) local emailFinish=$( cut -d ':' -f 2 <<< $1 ) local emailError=$( cut -d ':' -f 3 <<< $1 ) if [ -n "$emailStart" ];then case $emailStart in 1) EMAIL_START_ACTION="$EMAIL_START_ACTION_1" ;; 2) EMAIL_START_ACTION="$EMAIL_START_ACTION_2" ;; 3) EMAIL_START_ACTION="$EMAIL_START_ACTION_3" ;; 4) EMAIL_START_ACTION="$EMAIL_START_ACTION_4" ;; 5) EMAIL_START_ACTION="$EMAIL_START_ACTION_5" ;; 6) EMAIL_START_ACTION="$EMAIL_START_ACTION_6" ;; 7) EMAIL_START_ACTION="$EMAIL_START_ACTION_7" ;; 8) EMAIL_START_ACTION="$EMAIL_START_ACTION_8" ;; 9) EMAIL_START_ACTION="$EMAIL_START_ACTION_9" ;; 10) EMAIL_START_ACTION="$EMAIL_START_ACTION_10" ;; esac fi if [ -n "$emailFinish" ];then case $emailFinish in 1) EMAIL_FINISH_ACTION="$EMAIL_FINISH_ACTION_1" ;; 2) EMAIL_FINISH_ACTION="$EMAIL_FINISH_ACTION_2" ;; 3) EMAIL_FINISH_ACTION="$EMAIL_FINISH_ACTION_3" ;; 4) EMAIL_FINISH_ACTION="$EMAIL_FINISH_ACTION_4" ;; 5) EMAIL_FINISH_ACTION="$EMAIL_FINISH_ACTION_5" ;; 6) EMAIL_FINISH_ACTION="$EMAIL_FINISH_ACTION_6" ;; 7) EMAIL_FINISH_ACTION="$EMAIL_FINISH_ACTION_7" ;; 8) EMAIL_FINISH_ACTION="$EMAIL_FINISH_ACTION_8" ;; 9) EMAIL_FINISH_ACTION="$EMAIL_FINISH_ACTION_9" ;; 10) EMAIL_FINISH_ACTION="$EMAIL_FINISH_ACTION_10" ;; esac fi if [ -n "$emailError" ];then case $emailError in 1) EMAIL_ERROR_ACTION="$EMAIL_ERROR_ACTION_1" ;; 2) EMAIL_ERROR_ACTION="$EMAIL_ERROR_ACTION_2" ;; 3) EMAIL_ERROR_ACTION="$EMAIL_ERROR_ACTION_3" ;; 4) EMAIL_ERROR_ACTION="$EMAIL_ERROR_ACTION_4" ;; 5) EMAIL_ERROR_ACTION="$EMAIL_ERROR_ACTION_5" ;; 6) EMAIL_ERROR_ACTION="$EMAIL_ERROR_ACTION_6" ;; 7) EMAIL_ERROR_ACTION="$EMAIL_ERROR_ACTION_7" ;; 8) EMAIL_ERROR_ACTION="$EMAIL_ERROR_ACTION_8" ;; 9) EMAIL_ERROR_ACTION="$EMAIL_ERROR_ACTION_9" ;; 10) EMAIL_ERROR_ACTION="$EMAIL_ERROR_ACTION_10" ;; esac fi } # args: $1 - mount number set_mount_data() { case $1 in 1) MOUNT_BU_DISK=$MOUNT_BU_DISK_1 UNMOUNT_BU_DISK=$UNMOUNT_BU_DISK_1 ;; 2) MOUNT_BU_DISK=$MOUNT_BU_DISK_2 UNMOUNT_BU_DISK=$UNMOUNT_BU_DISK_2 ;; 3) MOUNT_BU_DISK=$MOUNT_BU_DISK_3 UNMOUNT_BU_DISK=$UNMOUNT_BU_DISK_3 ;; 4) MOUNT_BU_DISK=$MOUNT_BU_DISK_4 UNMOUNT_BU_DISK=$UNMOUNT_BU_DISK_4 ;; 5) MOUNT_BU_DISK=$MOUNT_BU_DISK_5 UNMOUNT_BU_DISK=$UNMOUNT_BU_DISK_5 ;; 6) MOUNT_BU_DISK=$MOUNT_BU_DISK_6 UNMOUNT_BU_DISK=$UNMOUNT_BU_DISK_6 ;; 7) MOUNT_BU_DISK=$MOUNT_BU_DISK_7 UNMOUNT_BU_DISK=$UNMOUNT_BU_DISK_7 ;; 8) MOUNT_BU_DISK=$MOUNT_BU_DISK_8 UNMOUNT_BU_DISK=$UNMOUNT_BU_DISK_8 ;; 9) MOUNT_BU_DISK=$MOUNT_BU_DISK_9 UNMOUNT_BU_DISK=$UNMOUNT_BU_DISK_9 ;; 10) MOUNT_BU_DISK=$MOUNT_BU_DISK_10 UNMOUNT_BU_DISK=$UNMOUNT_BU_DISK_10 ;; esac } # args: $1 - backup job number; $2 - set/print set_or_print_backup_job() { local backupJob='' backupJobData='' backupJobName='' case $1 in 1) backupJob="$BACKUP_JOB_1" ;; 2) backupJob="$BACKUP_JOB_2" ;; 3) backupJob="$BACKUP_JOB_3" ;; 4) backupJob="$BACKUP_JOB_4" ;; 5) backupJob="$BACKUP_JOB_5" ;; 6) backupJob="$BACKUP_JOB_6" ;; 7) backupJob="$BACKUP_JOB_7" ;; 8) backupJob="$BACKUP_JOB_8" ;; 9) backupJob="$BACKUP_JOB_9" ;; 10) backupJob="$BACKUP_JOB_10" ;; esac if [ -n "$( grep ':' <<< $backupJob )" ];then backupJobData=$( cut -d ':' -f 2-20 <<< $backupJob ) BACKUP_JOB_NAME=$( cut -d ':' -f 1 <<< $backupJob ) else backupJobData=$backupJob fi if [ -n "$BACKUP_JOB_NAME" ];then backupJobName=" ${C}$BACKUP_JOB_NAME${S}" fi # make sure the job has content if [ -n "$backupJob" -a "$backupJob" != ':' ];then if [ "$2" == 'set' ];then echo "${S}Your job presets are: ${C}$backupJobData" echo "${S}Restarting $SELF_NAME to run backup job$backupJobName (Job No. ${C}$1${S}) now...${N}" echo $LINE sleep 1 exec $SELF_PATH/$SELF_NAME -z $1 $backupJobData exit 0 elif [ "$2" == 'print' ];then echo "${M}You are currently about to run backup job number: ${C}$BACKUP_JOB_NU" echo "${S}Your job$backupJobName (Job No. ${C}$1${S}) presets are: ${C}$backupJobData${N}" fi else error_handler 17 "$1" fi } # args: $1 - data in format: x:y:z where x/y/z are null or 1-5 set_pre_post_data(){ local preMount=$( cut -d ':' -f 1 <<< $1 ) local postMount=$( cut -d ':' -f 2 <<< $1 ) local postUmount=$( cut -d ':' -f 3 <<< $1 ) if [ -n "$preMount" ];then case $preMount in 1) PRE_MOUNT_FUNCTION="$PRE_MOUNT_FUNCTION_1" ;; 2) PRE_MOUNT_FUNCTION="$PRE_MOUNT_FUNCTION_2" ;; 3) PRE_MOUNT_FUNCTION="$PRE_MOUNT_FUNCTION_3" ;; 4) PRE_MOUNT_FUNCTION="$PRE_MOUNT_FUNCTION_4" ;; 5) PRE_MOUNT_FUNCTION="$PRE_MOUNT_FUNCTION_5" ;; 6) PRE_MOUNT_FUNCTION="$PRE_MOUNT_FUNCTION_6" ;; 7) PRE_MOUNT_FUNCTION="$PRE_MOUNT_FUNCTION_7" ;; 8) PRE_MOUNT_FUNCTION="$PRE_MOUNT_FUNCTION_8" ;; 9) PRE_MOUNT_FUNCTION="$PRE_MOUNT_FUNCTION_9" ;; 10) PRE_MOUNT_FUNCTION="$PRE_MOUNT_FUNCTION_10" ;; esac fi if [ -n "$postMount" ];then case $postMount in 1) POST_MOUNT_FUNCTION="$POST_MOUNT_FUNCTION_1" ;; 2) POST_MOUNT_FUNCTION="$POST_MOUNT_FUNCTION_2" ;; 3) POST_MOUNT_FUNCTION="$POST_MOUNT_FUNCTION_3" ;; 4) POST_MOUNT_FUNCTION="$POST_MOUNT_FUNCTION_4" ;; 5) POST_MOUNT_FUNCTION="$POST_MOUNT_FUNCTION_5" ;; 6) POST_MOUNT_FUNCTION="$POST_MOUNT_FUNCTION_6" ;; 7) POST_MOUNT_FUNCTION="$POST_MOUNT_FUNCTION_7" ;; 8) POST_MOUNT_FUNCTION="$POST_MOUNT_FUNCTION_8" ;; 9) POST_MOUNT_FUNCTION="$POST_MOUNT_FUNCTION_9" ;; 10) POST_MOUNT_FUNCTION="$POST_MOUNT_FUNCTION_10" ;; esac fi if [ -n "$postUmount" ];then case $postUmount in 1) POST_UMOUNT_FUNCTION="$POST_UMOUNT_FUNCTION_1" ;; 2) POST_UMOUNT_FUNCTION="$POST_UMOUNT_FUNCTION_2" ;; 3) POST_UMOUNT_FUNCTION="$POST_UMOUNT_FUNCTION_3" ;; 4) POST_UMOUNT_FUNCTION="$POST_UMOUNT_FUNCTION_4" ;; 5) POST_UMOUNT_FUNCTION="$POST_UMOUNT_FUNCTION_5" ;; 6) POST_UMOUNT_FUNCTION="$POST_UMOUNT_FUNCTION_6" ;; 7) POST_UMOUNT_FUNCTION="$POST_UMOUNT_FUNCTION_7" ;; 8) POST_UMOUNT_FUNCTION="$POST_UMOUNT_FUNCTION_8" ;; 9) POST_UMOUNT_FUNCTION="$POST_UMOUNT_FUNCTION_9" ;; 10) POST_UMOUNT_FUNCTION="$POST_UMOUNT_FUNCTION_10" ;; esac fi } #### ------------------------------------------------------------------- #### set add, skip, clone data #### ------------------------------------------------------------------- # remember, -A overrides -S if they are the same SKIP item. # args: $1 - items to add, loops through all. set_add_data() { local addItem='' for addItem in $1 do case $addItem in d) B_SKIP_DATA_FULL='false' B_SKIP_DATA_1='false' B_SKIP_DATA_2='false' B_SKIP_DATA_3='false' B_SKIP_DATA_4='false' B_SKIP_DATA_5='false' B_SKIP_DATA_6='false' B_SKIP_DATA_7='false' B_SKIP_DATA_8='false' B_SKIP_DATA_9='false' B_SKIP_DATA_10='false' ;; h) B_SKIP_HOME='false' ;; r) B_SKIP_ROOT='false' ;; rh|hr) B_SKIP_HOME='false' B_SKIP_ROOT='false' ;; # note that B_SKIP_DATA_FULL='false' is required # to override the block off switch for DATA 1) B_SKIP_DATA_1='false' B_SKIP_DATA_FULL='false' ;; 2) B_SKIP_DATA_2='false' B_SKIP_DATA_FULL='false' ;; 3) B_SKIP_DATA_3='false' B_SKIP_DATA_FULL='false' ;; 4) B_SKIP_DATA_4='false' B_SKIP_DATA_FULL='false' ;; 5) B_SKIP_DATA_5='false' B_SKIP_DATA_FULL='false' ;; 6) B_SKIP_DATA_6='false' B_SKIP_DATA_FULL='false' ;; 7) B_SKIP_DATA_7='false' B_SKIP_DATA_FULL='false' ;; 8) B_SKIP_DATA_8='false' B_SKIP_DATA_FULL='false' ;; 9) B_SKIP_DATA_9='false' B_SKIP_DATA_FULL='false' ;; 10) B_SKIP_DATA_10='false' B_SKIP_DATA_FULL='false' ;; esac done } # args: $1 - directory/ies to be cloned set_clone_data() { case $1 in h) B_CLONE_HOME='true' HOME_DIR='home' B_SKIP_DATA_FULL='true' B_SKIP_ROOT='true' CLONE_SOURCE_DIR=$HOME_PATH ;; r) B_CLONE_ROOT='true' ROOT_DIR='' B_SKIP_DATA_FULL='true' B_SKIP_HOME='true' CLONE_SOURCE_DIR=$ROOT_PATH ;; 1) set_clone_skip_data B_CLONE_DATA_1='true' DATA_1_DIR='' CLONE_SOURCE_DIR=$DATA_1_PATH ;; 2) set_clone_skip_data B_CLONE_DATA_2='true' DATA_2_DIR='' CLONE_SOURCE_DIR=$DATA_2_PATH ;; 3) set_clone_skip_data B_CLONE_DATA_3='true' DATA_3_DIR='' CLONE_SOURCE_DIR=$DATA_3_PATH ;; 4) set_clone_skip_data B_CLONE_DATA_4='true' DATA_4_DIR='' CLONE_SOURCE_DIR=$DATA_4_PATH ;; 5) set_clone_skip_data B_CLONE_DATA_5='true' DATA_5_DIR='' CLONE_SOURCE_DIR=$DATA_5_PATH ;; 6) set_clone_skip_data B_CLONE_DATA_6='true' DATA_6_DIR='' CLONE_SOURCE_DIR=$DATA_6_PATH ;; 7) set_clone_skip_data B_CLONE_DATA_7='true' DATA_7_DIR='' CLONE_SOURCE_DIR=$DATA_7_PATH ;; 8) set_clone_skip_data B_CLONE_DATA_8='true' DATA_8_DIR='' CLONE_SOURCE_DIR=$DATA_8_PATH ;; 9) set_clone_skip_data B_CLONE_DATA_9='true' DATA_9_DIR='' CLONE_SOURCE_DIR=$DATA_9_PATH ;; 10) set_clone_skip_data B_CLONE_DATA_10='true' DATA_10_DIR='' CLONE_SOURCE_DIR=$DATA_10_PATH ;; esac # make sure no user error occured check_backup_source_directory "$CLONE_SOURCE_DIR" } # set all data to false except for # explicitly set clone item and FULL set_clone_skip_data() { B_SKIP_DATA_FULL='false' B_SKIP_DATA_1='true' B_SKIP_DATA_2='true' B_SKIP_DATA_3='true' B_SKIP_DATA_4='true' B_SKIP_DATA_5='true' B_SKIP_DATA_6='true' B_SKIP_DATA_7='true' B_SKIP_DATA_8='true' B_SKIP_DATA_9='true' B_SKIP_DATA_10='true' B_SKIP_HOME='true' B_SKIP_ROOT='true' } # remember, -A overrides -S if they are the same SKIP item. # args: $1 - items to skip, loops through all. set_skip_data() { local skipItem='' for skipItem in $1 do case $skipItem in d) B_SKIP_DATA_FULL='true' ;; h) B_SKIP_HOME='true' ;; r) B_SKIP_ROOT='true' ;; rh|hr) B_SKIP_HOME='true' B_SKIP_ROOT='true' ;; 1) B_SKIP_DATA_1='true' ;; 2) B_SKIP_DATA_2='true' ;; 3) B_SKIP_DATA_3='true' ;; 4) B_SKIP_DATA_4='true' ;; 5) B_SKIP_DATA_5='true' ;; 6) B_SKIP_DATA_6='true' ;; 7) B_SKIP_DATA_7='true' ;; 8) B_SKIP_DATA_8='true' ;; 9) B_SKIP_DATA_9='true' ;; 10) B_SKIP_DATA_10='true' ;; esac done } #### ------------------------------------------------------------------- #### primary backup tools #### ------------------------------------------------------------------- run_backup_question() { local opt='' options='' doTheBackup='' removeBackup='' repeat='' local removeDeleteOpt='' nullCloneSource='' cloneSource='' rsyncSim1=' backup' rsyncSim2='' # need to check destination data here, after mount, but not need to recheck if same as # initial if [ "$BACKUP_LOCATION" != "$BACKUP_MOUNT_POINT" ];then check_backup_destination_directory "$BACKUP_LOCATION" fi echo $MLINE print_version_info 'main' echo $MLINE echo "${M}Working backup location: ${C}$BACKUP_LOCATION${N}" echo $MLINE print_history_data 'main' echo $MLINE if [ "$BACKUP_JOB_NU" != 'none' ];then set_or_print_backup_job "$BACKUP_JOB_NU" 'print' echo $LINE fi if [ "$BACKUP_APP" == 'rsync' ] && [ "$B_DRY_RUN" == 'true' -o -n "$( grep 'dry-run' <<< $RSYNC_EXTRA_OPTIONS )" ];then echo "${M}You are using the ${C}rsync --dry-run${M} option, which simulates your backup." echo "${S}This option lets you see what would happen, before you really run the backup." echo $LINE rsyncSim1=" ${C}simulate${S} the backup of" rsyncSim2=" ${C}simulation${M} of a" fi if [ "$B_IS_CLONE" == 'true' ];then if [ -z "$CLONE_SOURCE_DIR" ];then nullCloneSource='echo -e "${M}Your Clone Source Directory is ${W}empty${M}.${S} Unless you are cloning ${C}root${S}, this is\nprobably a mistake. Make sure this is correct before you proceed please.\n"' cloneSource='empty' else cloneSource=$CLONE_SOURCE_DIR fi echo "${M}You are about to run a$rsyncSim2 direct ${C}Clone job${M} (${C}-C${M}) using these directories:${S}" echo "Source Directory: ${C}$cloneSource${S} :: Destination Directory: ${C}$BACKUP_MOUNT_POINT" echo eval "$nullCloneSource" echo "${S}Cloning will sync all destination files with your source directory files, and remove" echo "any obsolete files from the destination directory. ${W}BE CAREFUL WITH THIS!!!" echo $LINE echo "${C}1 - run-clone-job${S} - Clones the above Source Data to Destination directory." echo echo "${C}2 - quit${S} - Don't do the Clone after all, exit script." options="run-clone-job quit" else case "$BACKUP_APP" in rdiff-backup) echo "${S}Backups use standard ${C}$BACKUP_APP${S} settings, which lets you restore from any time" echo "period stored in the full backup. After first full backup, the next ones will be" echo "incremental backups, which run much faster since they only backup changed files." ;; rsync) echo "${S}This will$rsyncSim1 your system to the backup directories you have already" echo "set up for your ${C}$BACKUP_APP${S} backup." ;; esac echo $LINE echo "${S}Please select one of the following numbers to assign the correct backup option." echo "${C}1 - backup-normal${S} - Backs up as usual with $BACKUP_APP. Does not remove old backups." case "$BACKUP_APP" in rdiff-backup) echo "${C}2 - clean-older${S} - Removes all backup increments older than your time setting: $RDIFF_REMOVE_TIME" echo " After the cleanup, runs a new standard backup." removeDeleteOpt='clean-older' ;; rsync) echo "${C}2 - clean-obsolete${S} - Removes all backed up up files that have been deleted from" echo " your current install." removeDeleteOpt='clean-obsolete' ;; esac echo "${C}3 - backup-and-delete-old${S} - Backs up but first deletes old backups. This is final, " echo " so once you agree to remove, no restore of older material will be possible. This will" echo " delete the backup that corresponds to the currently active primary backup directory." echo echo "${C}4 - quit${S} - Don't do the backup after all, exit script." options="backup-normal $removeDeleteOpt backup-and-delete-old quit" fi echo $LINE select opt in $options do log_function_data 'data' "User Option Selection: $opt" case $opt in backup-normal) doTheBackup='true' ;; backup-and-delete-old) removeBackup='true' doTheBackup='true' ;; # rdiff-backup only clean-older) # first get rid of all older files and increments B_CLEAN_OLDER='true' run_backup_components B_CLEAN_OLDER='false' doTheBackup='true' ;; # rsync only clean-obsolete) B_CLEAN_OLDER='true' doTheBackup='true' ;; run-clone-job) B_CLEAN_OLDER='true' doTheBackup='true' ;; quit) echo "${S}Ok, no backup today, exiting the script...${N}" exit 0 ;; *) echo $ELINE echo "${E}You need to type in one of above the numbers!!${N}" repeat='true' ;; esac break done if [ "$repeat" == 'true' ];then run_backup_question fi if [ "$removeBackup" == 'true' ];then remove_backups fi if [ "$doTheBackup" == 'true' ];then run_backup_components fi } remove_backups() { local options='' opt='' repeat='' deleteBackup='' directory='' directories='' local backupDirectories=$( ls $BACKUP_LOCATION ) # dump line breaks for directory in $backupDirectories do directories="$directories$directory " done if [ -z "$backupDirectories" ];then directories='No Directories to Delete ' fi echo $LINE echo "${Q}Are you sure you want to delete the contents of your backup directories?${N}" echo echo "${S}These directories will be removed: ${C}$directories${S}in ${C}$BACKUP_LOCATION" echo echo "${C}1 - yes-delete${S} - Deletes ALL directories in ${C}$BACKUP_LOCATION" echo "${C}2 - no-keep${S} - Keeps current data in ${C}$BACKUP_LOCATION${S} and backs up as normal." echo "${C}3 - quit${S} - Quit, think about it later." echo $LINE options='yes-delete no-keep quit' select opt in $options do log_function_data 'data' "User Option Selection: $opt" case $opt in yes-delete) deleteBackup='true' ;; no-keep) echo $LINE echo "${S}Ok, no deleting of them today." echo echo "Continuing with backup now...${N}" ;; quit) echo "${S}Ok, no backup today, exiting the script...${N}" exit 0 ;; *) echo $ELINE echo "${E}You need to type in one of above the numbers!!${N}" repeat='true' ;; esac break done if [ "$repeat" == 'true' ];then remove_backups fi if [ "$deleteBackup" == 'true' ];then delete_old_backup fi } delete_old_backup() { local removedDirectories=$( ls $BACKUP_LOCATION ) directory='' echo $LINE if [ -n "$removedDirectories" ];then log_function_data 'data' "delete_old_backup - Directories to be deleted:\n$removedDirectories" GET_PID='' echo -n "${S}Starting deletion of " for directory in $removedDirectories do echo -n "${C}$directory${S} " done echo -n "in ${C}$BACKUP_LOCATION${N}" echo echo -n "${S}This could take a while, be patient$ENDING_2${N}" if [ "$B_SPINNING_WHEEL" != 'true' ];then echo echo # clear that -n fi for directory in $removedDirectories do # as ghstryder pointed out, this should also be dry run supporting so people don't # get unexpected result of deleting their actual backup with -r (--dry-run) option if [ "$B_DRY_RUN" != 'true' ];then if [ "$B_SPINNING_WHEEL" == 'true' ];then rm -fr $BACKUP_LOCATION/$directory & GET_PID="$!" spinning_wheel_activity_indicator delete wait else echo -n "${S}Deleting ${C}$BACKUP_LOCATION/$directory${S} now.....${N}" rm -fr $BACKUP_LOCATION/$directory echo "${S}... ${M}directory deleted${N}" fi else echo -n "${S}Dry run (${C}-r${S}) emulation mode: Deleting ${C}$BACKUP_LOCATION/$directory${S} now.....${N}" fi done else echo -n "${M}There is nothing to delete, continuing with backup...${N}" log_function_data 'data' "delete_old_backup - No Directories to be deleted" fi DELETION_TEXT=' deletion and' echo echo "${S}Starting backup now...${N}" sleep $SLEEP_TIME_BACKUP B_DELETE_STATUS='true' } run_backup_components() { # set rdiff-backup/rsync commands. Must be here because delete data might be # set for rsync set_backup_commands # If you don't need excludes in /home, then just delete the exclude stuff, --exclude... echo $LINE log_function_data 'data' "run_backup_components: begin\n\n" #backup home directory if [ "$B_CLONE_HOME" == 'true' ] || [ "$HOME_DIR" != '' -a "$B_SKIP_HOME" != 'true' ];then check_backup_source_directory "$HOME_PATH" log_function_data 'data' "Starting Home Backup Command:\n$HOME_BU_COMMAND" echo -n "${S}$BACKUP_CLEAR ${C}home${S} directory$ENDING_1${N}" if [ "$B_SPINNING_WHEEL" == 'true' ];then GET_PID='' eval $HOME_BU_COMMAND & GET_PID="$!" spinning_wheel_activity_indicator backup home else eval $HOME_BU_COMMAND || error_handler 25 "$?" echo fi log_function_data 'data' "Finished Home\n\n" sleep $SLEEP_TIME_BACKUP fi # backup system root directory if [ "$B_CLONE_ROOT" == 'true' ] || [ "$ROOT_DIR" != '' -a "$B_SKIP_ROOT" != 'true' ];then check_backup_source_directory "$ROOT_PATH" log_function_data 'data' "Starting Root Backup Command:\n$ROOT_BU_COMMAND" echo -n "${S}$BACKUP_CLEAR ${C}root${S} directory ${C}$ROOT_DESC${S}$ENDING_1${N}" if [ "$B_SPINNING_WHEEL" == 'true' ];then GET_PID='' eval $ROOT_BU_COMMAND & GET_PID="$!" spinning_wheel_activity_indicator backup $ROOT_DESC else eval $ROOT_BU_COMMAND || error_handler 25 "$?" echo fi log_function_data 'data' "Finished Root\n\n" fi if [ "$B_SKIP_DATA_FULL" != 'true' ];then # backup optional user data 1 if [ "$B_CLONE_DATA_1" == 'true' ] || [ "$DATA_1_DIR" != '' -a "$B_SKIP_DATA_1" != 'true' ];then check_backup_source_directory "$DATA_1_PATH" log_function_data 'data' "Starting Data 1 Backup Command:\n$DATA_1_BU_COMMAND" echo -n "${S}$BACKUP_CLEAR ${C}$DATA_1_DESC${S} directory$ENDING_1${N}" if [ "$B_SPINNING_WHEEL" == 'true' ];then GET_PID='' eval $DATA_1_BU_COMMAND & GET_PID="$!" spinning_wheel_activity_indicator backup $DATA_1_DESC else eval $DATA_1_BU_COMMAND || error_handler 25 "$?" echo fi log_function_data 'data' "Finished Data 1\n\n" sleep $SLEEP_TIME_BACKUP fi # backup optional user data 2 if [ "$B_CLONE_DATA_2" == 'true' ] || [ "$DATA_2_DIR" != '' -a "$B_SKIP_DATA_2" != 'true' ];then check_backup_source_directory "$DATA_2_PATH" log_function_data 'data' "Starting Data 2 Backup Command:\n$DATA_2_BU_COMMAND" echo -n "${S}$BACKUP_CLEAR ${C}$DATA_2_DESC${S} directory$ENDING_1${N}" if [ "$B_SPINNING_WHEEL" == 'true' ];then GET_PID='' eval $DATA_2_BU_COMMAND & GET_PID="$!" spinning_wheel_activity_indicator backup $DATA_2_DESC else eval $DATA_2_BU_COMMAND || error_handler 25 "$?" echo fi log_function_data 'data' "Finished Data 2\n\n" sleep $SLEEP_TIME_BACKUP fi # backup optional user data 3 if [ "$B_CLONE_DATA_3" == 'true' ] || [ "$DATA_3_DIR" != '' -a "$B_SKIP_DATA_3" != 'true' ];then check_backup_source_directory "$DATA_3_PATH" log_function_data 'data' "Starting Data 3 Backup Command:\n$DATA_3_BU_COMMAND" echo -n "${S}$BACKUP_CLEAR ${C}$DATA_3_DESC${S} directory$ENDING_1${N}" if [ "$B_SPINNING_WHEEL" == 'true' ];then GET_PID='' eval $DATA_3_BU_COMMAND & GET_PID="$!" spinning_wheel_activity_indicator backup $DATA_3_DESC else eval $DATA_3_BU_COMMAND || error_handler 25 "$?" echo fi log_function_data 'data' "Finished Data 3\n\n" sleep $SLEEP_TIME_BACKUP fi # backup optional user data 4 if [ "$B_CLONE_DATA_4" == 'true' ] || [ "$DATA_4_DIR" != '' -a "$B_SKIP_DATA_4" != 'true' ];then check_backup_source_directory "$DATA_4_PATH" log_function_data 'data' "Starting Data 4 Backup Command:\n$DATA_4_BU_COMMAND" echo -n "${S}$BACKUP_CLEAR ${C}$DATA_4_DESC${S} directory$ENDING_1${N}" if [ "$B_SPINNING_WHEEL" == 'true' ];then GET_PID='' eval $DATA_4_BU_COMMAND & GET_PID="$!" spinning_wheel_activity_indicator backup $DATA_4_DESC else eval $DATA_4_BU_COMMAND || error_handler 25 "$?" echo fi log_function_data 'data' "Finished Data 4\n\n" sleep $SLEEP_TIME_BACKUP fi # backup optional user data 5 if [ "$B_CLONE_DATA_5" == 'true' ] || [ "$DATA_5_DIR" != '' -a "$B_SKIP_DATA_5" != 'true' ];then check_backup_source_directory "$DATA_5_PATH" log_function_data 'data' "Starting Data 5 Backup Command:\n$DATA_5_BU_COMMAND" echo -n "${S}$BACKUP_CLEAR ${C}$DATA_5_DESC${S} directory$ENDING_1${N}" if [ "$B_SPINNING_WHEEL" == 'true' ];then GET_PID='' eval $DATA_5_BU_COMMAND & GET_PID="$!" spinning_wheel_activity_indicator backup $DATA_5_DESC else eval $DATA_5_BU_COMMAND || error_handler 25 "$?" echo fi log_function_data 'data' "Finished Data 5\n\n" sleep $SLEEP_TIME_BACKUP fi # backup optional user data 2 if [ "$B_CLONE_DATA_6" == 'true' ] || [ "$DATA_6_DIR" != '' -a "$B_SKIP_DATA_6" != 'true' ];then check_backup_source_directory "$DATA_6_PATH" log_function_data 'data' "Starting Data 6 Backup Command:\n$DATA_6_BU_COMMAND" echo -n "${S}$BACKUP_CLEAR ${C}$DATA_6_DESC${S} directory$ENDING_1${N}" if [ "$B_SPINNING_WHEEL" == 'true' ];then GET_PID='' eval $DATA_6_BU_COMMAND & GET_PID="$!" spinning_wheel_activity_indicator backup $DATA_6_DESC else eval $DATA_6_BU_COMMAND || error_handler 25 "$?" echo fi log_function_data 'data' "Finished Data 6\n\n" sleep $SLEEP_TIME_BACKUP fi # backup optional user data 7 if [ "$B_CLONE_DATA_7" == 'true' ] || [ "$DATA_7_DIR" != '' -a "$B_SKIP_DATA_7" != 'true' ];then check_backup_source_directory "$DATA_7_PATH" log_function_data 'data' "Starting Data 7 Backup Command:\n$DATA_7_BU_COMMAND" echo -n "${S}$BACKUP_CLEAR ${C}$DATA_7_DESC${S} directory$ENDING_1${N}" if [ "$B_SPINNING_WHEEL" == 'true' ];then GET_PID='' eval $DATA_7_BU_COMMAND & GET_PID="$!" spinning_wheel_activity_indicator backup $DATA_7_DESC else eval $DATA_7_BU_COMMAND || error_handler 25 "$?" echo fi log_function_data 'data' "Finished Data 7\n\n" sleep $SLEEP_TIME_BACKUP fi # backup optional user data 8 if [ "$B_CLONE_DATA_8" == 'true' ] || [ "$DATA_8_DIR" != '' -a "$B_SKIP_DATA_8" != 'true' ];then check_backup_source_directory "$DATA_8_PATH" log_function_data 'data' "Starting Data 8 Backup Command:\n$DATA_8_BU_COMMAND" echo -n "${S}$BACKUP_CLEAR ${C}$DATA_8_DESC${S} directory$ENDING_1${N}" if [ "$B_SPINNING_WHEEL" == 'true' ];then GET_PID='' eval $DATA_8_BU_COMMAND & GET_PID="$!" spinning_wheel_activity_indicator backup $DATA_8_DESC else eval $DATA_8_BU_COMMAND || error_handler 25 "$?" echo fi log_function_data 'data' "Finished Data 8\n\n" sleep $SLEEP_TIME_BACKUP fi # backup optional user data 9 if [ "$B_CLONE_DATA_9" == 'true' ] || [ "$DATA_9_DIR" != '' -a "$B_SKIP_DATA_9" != 'true' ];then check_backup_source_directory "$DATA_9_PATH" log_function_data 'data' "Starting Data 9 Backup Command:\n$DATA_9_BU_COMMAND" echo -n "${S}$BACKUP_CLEAR ${C}$DATA_9_DESC${S} directory$ENDING_1${N}" if [ "$B_SPINNING_WHEEL" == 'true' ];then GET_PID='' eval $DATA_9_BU_COMMAND & GET_PID="$!" spinning_wheel_activity_indicator backup $DATA_9_DESC else eval $DATA_9_BU_COMMAND || error_handler 25 "$?" echo fi log_function_data 'data' "Finished Data 9\n\n" sleep $SLEEP_TIME_BACKUP fi # backup optional user data 10 if [ "$B_CLONE_DATA_10" == 'true' ] || [ "$DATA_10_DIR" != '' -a "$B_SKIP_DATA_10" != 'true' ];then check_backup_source_directory "$DATA_10_PATH" log_function_data 'data' "Starting Data 10 Backup Command:\n$DATA_10_BU_COMMAND" echo -n "${S}$BACKUP_CLEAR ${C}$DATA_10_DESC${S} directory$ENDING_1${N}" if [ "$B_SPINNING_WHEEL" == 'true' ];then GET_PID='' eval $DATA_10_BU_COMMAND & GET_PID="$!" spinning_wheel_activity_indicator backup $DATA_10_DESC else eval $DATA_10_BU_COMMAND || error_handler 25 "$?" echo fi log_function_data 'data' "Finished Data 10\n\n" sleep $SLEEP_TIME_BACKUP fi fi log_function_data 'data' "run_backup_components: end\n$LI\n" # this is set to false either in the main rsync assigner or by rdiff feature if [ "$B_CLEAN_OLDER" != 'true' ];then finish_backup else echo $LINE echo "${S}Ok, finished cleaning up older backup increments, running main backup now...${N}" sleep $SLEEP_TIME_BACKUP fi } #### ------------------------------------------------------------------- #### Backup start/pre/post/finish functions #### ------------------------------------------------------------------- mount_backup_disk() { local retNu=0 if [ "$MOUNT_BU_DISK" != '' -a "$B_SKIP_MOUNT" != 'true' ];then # found a possible error case here with null backup directory: log_function_data 'data' "BACKUP_MOUNT_POINT: $BACKUP_MOUNT_POINT\nMount Data: $MOUNT_BU_DISK" if [ -z "$BACKUP_MOUNT_POINT" ];then error_handler 26 fi echo -n "${S}Mounting backup drive/partition to ${C}$BACKUP_MOUNT_POINT${S}....${N}" eval $MOUNT_BU_DISK || retNu=$? if [ "$retNu" -eq 0 ];then echo "${S}....${M}mounted${N}" log_function_data 'data' "Mounted" else echo "${S}....${W}MOUNT FAILED!${N}" error_handler 2 "$retNu" fi # set the trap here trap 'trap_handler umount' INT TERM EXIT fi } # args: $1 - start/finish/error; $2 - data to be processed, error message, script start options run_emailer_tasks() { # strip out colors if present local data=$( echo -e "$2" | sed 's/\x1b\[[0-9]\{1,2\}\(;[0-9]\{1,2\}\)\{0,2\}m//g' ) local actionTime=$( date +"%Y %B %e - %R:%S" ) # then construct the string data="Rbxi $1: $actionTime\n$data" # note that the action must be in quotes when you execute it with eval case $1 in start) if [ -n "$EMAIL_START_ACTION" ];then log_function_data 'data' "Begin emailer task: start action" echo $LINE echo "${S}Running user action: ${C}start${N}" eval "$EMAIL_START_ACTION" fi ;; finish) if [ -n "$EMAIL_FINISH_ACTION" ];then log_function_data 'data' "Begin emailer task: finish action" echo $LINE echo "${S}Running user action: ${C}finish${N}" eval "$EMAIL_FINISH_ACTION" fi ;; error) if [ -n "$EMAIL_ERROR_ACTION" ];then log_function_data 'data' "Begin emailer task: error action" echo $LINE echo "${S}Running user action: ${C}error${N}" eval "$EMAIL_ERROR_ACTION" fi ;; esac } # args: $1 - pre-mount/post-mount/post-umount run_pre_post_tasks() { # note that the function must be in quotes when you declare it with eval case $1 in pre-mount) if [ -n "$PRE_MOUNT_FUNCTION" ];then log_function_data 'data' "Begin pre post tasks: pre mount function" echo $LINE echo "${S}Running user defined function: ${C}pre_mount_tasks()${N}" eval "$PRE_MOUNT_FUNCTION" pre_mount_tasks || error_handler 27 "$?" fi ;; post-mount) if [ -n "$POST_MOUNT_FUNCTION" ];then log_function_data 'data' "Begin pre post tasks: post mount function" echo $LINE echo "${S}Running user defined function: ${C}post_mount_tasks()${N}" eval "$POST_MOUNT_FUNCTION" post_mount_tasks || error_handler 28 "$?" fi ;; post-umount) if [ -n "$POST_UMOUNT_FUNCTION" ];then log_function_data 'data' "Begin pre post tasks: error function" echo $LINE echo "${S}Running user defined function: ${C}post_umount_tasks()${N}" eval "$POST_UMOUNT_FUNCTION" post_umount_tasks || error_handler 29 "$?" fi ;; esac } #### ------------------------------------------------------------------- #### Backup completion functions #### ------------------------------------------------------------------- finish_backup() { # set the DURATION global here as well prior to updating configs print_the_end_time update_configs umount_backup_disk run_pre_post_tasks 'post-umount' print_complete_message log_function_data 'data' "Backup Job Completed.\n\n" run_emailer_tasks 'finish' "Completed. Start Options: $SELF_OPTIONS" } update_configs() { local backupDate=$( date +"%Y-%m-%d - %R" ) local cloneJob='' backupJobName='' if [ "$B_IS_CLONE" == 'true' -a -n "$CLONE_SOURCE_DIR" ];then cloneJob=" :: Cloned: $CLONE_SOURCE_DIR" fi if [ -n "$BACKUP_JOB_NAME" ];then backupJobName=" ($BACKUP_JOB_NAME)" fi local backupString="Location: $BACKUP_LOCATION :: Date: $backupDate~Run Time: $BACKUP_DURATION :: Deletion: $B_DELETE_STATUS :: Job No: $BACKUP_JOB_NU$backupJobName$cloneJob" echo $LINE echo "${S}Updating backup records now...${N}" sed -i "s%last-backup-directory=.*%last-backup-directory=$BACKUP_LOCATION%" $SELF_CONFIGS sed -i "s/last-backup-date=.*/last-backup-date=$backupDate/" $SELF_CONFIGS sed -i "s/last-backup-duration=.*/last-backup-duration=$BACKUP_DURATION/" $SELF_CONFIGS sed -i "s/last-backup-app=.*/last-backup-app=$BACKUP_APP/" $SELF_CONFIGS sed -i "s/last-backup-job=.*/last-backup-job=$BACKUP_JOB_NU/" $SELF_CONFIGS case "$BACKUP_APP" in rdiff-backup) sed -i "s%rdbu-backup-history=.*%rdbu-backup-history=$backupString%" $SELF_CONFIGS ;; rsync) sed -i "s%rsync-backup-history=.*%rsync-backup-history=$backupString%" $SELF_CONFIGS ;; esac log_function_data 'data' "Completed Backup Config Data:\n$( cat $SELF_CONFIGS )\n$LI\n" } # do some arithmetic on time print_the_end_time() { local endTime=$( date +%s ) local completedTime=$(( $endTime - $START_TIME )) local hours=$(( $completedTime / 3600 )) local remainingMinutes=$(( $completedTime % 3600 )) local minutes=$(( $remainingMinutes / 60 )) local seconds=$(( $remainingMinutes % 60 )) local hourText='' minuteText='' secondText='' plural='' # set hours, if needed if [ "$hours" -ne 0 ];then if [ "$hours" -gt 1 ];then plural='s' else plural='' fi hourText=" ${C}$hours${S} hour$plural," fi # set minutes if [ "$minutes" -gt 1 -o "$minutes" -eq 0 ];then plural='s' else plural='' fi minuteText=" ${C}$minutes${S} minute$plural," # set seconds if [ "$seconds" -gt 1 -o "$seconds" -eq 0 ];then plural='s' else plural='' fi secondText=" ${C}$seconds${S} second$plural" echo "${S}The$DELETION_TEXT backup took$hourText$minuteText$secondText to complete.${N}" # zero pad the data minutes=$( printf %02d $minutes ) seconds=$( printf %02d $seconds ) BACKUP_DURATION=$hours:$minutes:$seconds } umount_backup_disk() { local retNu=0 if [ "$MOUNT_BU_DISK" != '' -a "$B_SKIP_MOUNT" != 'true' ];then log_function_data 'data' "BACKUP_MOUNT_POINT: $BACKUP_MOUNT_POINT\nUmount Data: $UNMOUNT_BU_DISK" echo echo "Running sync to make sure writes to drives are done (can take a while)...${N}" sync echo -n "${S}Unmounting your backup partition $BACKUP_MOUNT_POINT now...${N}" eval $UNMOUNT_BU_DISK || retNu=$? if [ "$retNu" -eq 0 ];then echo "${S}.....${M}successfully unmounted.${N}" log_function_data 'data' "Umount successful." else echo "${S}.....${W}UMOUNT FAILED!${N}" error_handler 3 "$retNu" fi trap - INT TERM EXIT fi } print_complete_message() { echo $MLINE echo "${M}Ok, all done backing up for today!" echo $MLINE } ################################################################### ##### EXECUTE SCRIPT COMPONENTS ################################################################### set_self_colors check_self_requires get_options "$@" run_emailer_tasks 'start' "Start Options: $SELF_OPTIONS" # Make sure user is logged in as root first and that backup location is present check_startup_stuff log_function_data 'start' "$SELF_OPTIONS" # this sets the correct startup path so that exclude lists load correctly check_self_path # any updates that need to be run will be run here, should only be required # at rare intervals. check_self_changes # set rsync/rdiff-backup variables set_primary_backup_data # initialize the backup directory values set_backup_destination_data run_pre_post_tasks 'pre-mount' # then, if you use this, mount your backup drive mount_backup_disk run_pre_post_tasks 'post-mount' # note that this block only runs if the -a,-c, or -d flags are used, or if these # are set in a job or preset file. # for option deletion-run/run/clean-run. You can only run one of these, not more. if [ "$B_DELETE_BACKUP" == 'true' ];then delete_old_backup # this is for rdiff only, we need to run first the cleanup job, then # next send it to the main backup. elif [ "$B_CLEAN_OLDER" == 'true' -a "$BACKUP_TYPE" == 'rdiff-backup' ];then run_backup_components # must reset so we don't run the rdiff-cleanup stuff again B_CLEAN_OLDER='false' fi # skip the intro question and do it automatically if [ "$B_DO_BACKUP" == 'true' ];then run_backup_components # otherwise ask what options to use else run_backup_question fi ## extra information: #SpecialFileError var/run/acpid.socket Socket error: AF_UNIX path too long #SpecialFileError var/run/dbus/system_bus_socket Socket error: AF_UNIX path too long #SpecialFileError var/run/dirmngr/socket Socket error: AF_UNIX path too long #SpecialFileError var/run/mysqld/mysqld.sock Socket error: AF_UNIX path too long #SpecialFileError var/run/pcscd.comm Socket error: AF_UNIX path too long #SpecialFileError var/run/xdmctl/dmctl/socket Socket error: AF_UNIX path too long #SpecialFileError var/run/xdmctl/dmctl-:0/socket Socket error: AF_UNIX path too long exit 0 ###**EOF**###