Use at own risk. Programs haven't been thoroughly tested.
script: ksecure_backup.bash
A simple backup utility. Use it to backup your internet server. A simple incremental backup utility with support for: - filesystem backups - mysql dump - svn backup - incremental backups - rsync upload - ftp upload - optional encryption - optional compression - separate config file - automatic upgrades of the script
Info
@author Kevin van Zonneveld
@version 0.825
@link http://kevin.vanzonneveld.net
@version 0.825
@link http://kevin.vanzonneveld.net
Example
Usage
Outputs
[in /var/log/ksecure_backup.log, mail, or stdout]
./ksecure_backup.bash
Outputs
[in /var/log/ksecure_backup.log, mail, or stdout]
Source Code
download source#!/bin/bash # ########################################################################## # intialize # ########################################################################## PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11:/root/bin" RUN_WARNINGS=0 ########################################################################## # functions # ########################################################################## missing_var(){ logit "fatal: The setting ${1} is missing and I was unable to give it a default value! Please manually set the ${1} variable" } missing_cmd(){ COMMAND="${1}" COMMAND_UC=$(echo ${COMMAND} | tr 'a-z' 'A-Z') PACKAGE="${2}" MODE="${3}" [ -n ${PACKAGE} ] || PACKAGE=${COMMAND} if [ "${MODE}" == "install" ];then dia_YesNo "Missing Package" "Do you want to try to automatically install ${PACKAGE}?" INSTALL=${dia_ret} if [ "${INSTALL}" == 1 ]; then if [ -n ${CMD_APTITUDE} ];then ${CMD_APTITUDE} install -y ${PACKAGE} else logit "fatal: cannot find apt-get. please install ${COMMAND}(${PACKAGE}) by hand, and retry"; fi fi # second check TMPCMD=$(which ${COMMAND}) [ -n "${TMPCMD}" ] && [ -x ${TMPCMD} ] || logit "fatal: I still cannot find ${COMMAND}, but it is required to run this script" eval "CMD_${COMMAND_UC}=\"${TMPCMD}\"" elif [ "${MODE}" == "run" ];then logit "fatal: The command ${COMMAND} is missing! Please first install ${PACKAGE} (mode=${MODE})" fi } function dia_YesNo(){ # arg1 = title # arg2 = description xtra="" if [ "${3}" == "0" ]; then xtra="--defaultno" fi if [ -n "${CMD_DIALOG}" ] && [ -x ${CMD_DIALOG} ]; then ${CMD_DIALOG} ${xtra} --title "${1}" --clear \ --yesno "${2}" 10 70 case $? in 0) dia_ret=1;; 1) dia_ret=0;; 255) clear echo "ESC pressed." exit 0 ;; esac else while true; do echo -n "${1}. ${2} (Y/n) " read yn case $yn in "y" | "Y" | "" ) dia_ret=1 break ;; "n" | "N" ) dia_ret=0 break ;; * ) echo "unknown response. Asking again" ;; esac done fi } dia_Input(){ # arg1 = title # arg2 = description # arg3 = default ${CMD_DIALOG} --title "${1}" --clear \ --inputbox "${2}" 16 71 "${3}" 2> $tempfile retval=$? case $retval in 0) dia_ret=$(cat $tempfile);; 1) clear echo "Cancel pressed." exit 0 ;; 255) if test -s $tempfile ; then cat $tempfile else clear echo "ESC pressed." exit 0 fi ;; esac } dia_Select(){ # arg1 = title # arg2 = description # arg3-8 = menu CHOICES="" [ -z "${3}" ] || CHOICES="${CHOICES}${3} <-" [ -z "${4}" ] || CHOICES="${CHOICES} ${4} <-" [ -z "${5}" ] || CHOICES="${CHOICES} ${5} <-" [ -z "${6}" ] || CHOICES="${CHOICES} ${6} <-" [ -z "${7}" ] || CHOICES="${CHOICES} ${7} <-" [ -z "${8}" ] || CHOICES="${CHOICES} ${8} <-" ${CMD_DIALOG} --clear --title "${1}" \ --menu "${2}" 16 51 6 \ ${CHOICES} 2> $tempfile retval=$? choice=`cat $tempfile` case $retval in 0) dia_ret=${choice};; 1) clear echo "Cancel pressed." exit 0 ;; 255) clear echo "ESC pressed." exit 0 ;; esac } logit(){ MONTHNAME=$(${CMD_DATE} '+%B') LOG_DATE="${MONTHNAME:0:3} $(${CMD_DATE} '+%d %H:%M:%S')" LOG_LASTLINE="${LOG_DATE} $1" [ -z "${DB_PASS}" ] || LOG_LASTLINE=$(echo ${LOG_LASTLINE} |${CMD_SED} "s/${DB_PASS}/xxxxxx/g") [ -z "${FTP_PASS}" ] || LOG_LASTLINE=$(echo ${LOG_LASTLINE} |${CMD_SED} "s/${FTP_PASS}/xxxxxx/g") [ -z "${RSYNC_PASS}" ] || LOG_LASTLINE=$(echo ${LOG_LASTLINE} |${CMD_SED} "s/${RSYNC_PASS}/xxxxxx/g") if [ "${OUTPUT_ENABLED}" == 1 ] ;then if [ "${1:0:5}" == "debug" ] && [ "${OUTPUT_DEBUGENABLED}" == 1 ];then # output debugging information only when OUTPUT_DEBUGENABLED is on echo "${LOG_LASTLINE}" elif [ "${1:0:5}" != "debug" ];then # output non debugging information echo "${LOG_LASTLINE}" fi fi if [ "${LOG_ENABLED}" == 1 ] ;then # store everything in the logfile echo "${LOG_LASTLINE}" >> $LOG_FILE fi # set warning flag if [ "${1:0:7}" = "warning" ] || [ "${1:0:8}" = "critical" ] || [ "${1:0:5}" = "fatal" ];then RUN_WARNINGS=1 fi if [ "${1:0:5}" = "fatal" ]; then quit fi } is_running() { baseproc=$(basename ${1}) myproc=${2} processes=$(${CMD_PGREP} ${baseproc}) running_pid=0 for proc in ${processes};do # exclude our own process id! if [ ${proc} -ne ${myproc} ];then running_pid=${proc} fi done } quit(){ # cleanup [ -f "${APP_ACNTFILE}" ] && ${CMD_RM} -f ${APP_ACNTFILE} [ -f "${APP_UPDTFILE}" ] && ${CMD_RM} -f ${APP_UPDTFILE} if [ "${RUN_WARNINGS}" == 1 ];then # some things went wrong, handle reporting logit "debug: quitting, warnings occured during this run" if [ "${MAIL_ENABLED}" == 1 ] && [ -n "${CMD_MAIL}" ] && [ -x ${CMD_MAIL} ]; then # mail warnings logit "debug: trying to mail" ${CMD_TAIL} -n10 ${LOG_FILE} | ${CMD_MAIL} -s "[${APP_BASENAME}]@[${APP_HOSTNAME}] warnings " ${MAIL_TO} 1>/dev/null 2>>${LOG_FILE} if [ $? -ne 0 ]; then logit "critical: Mailing of warnings returned errors, more details in ${LOG_FILE}" fi elif [ ! "${OUTPUT_ENABLED}" == 1 ];then # output warnings even though ${OUTPUT_ENABLED} is off, because mail is also disabled! logit "debug: fatal error occured but i cannot mail and i am not allowed to write to standard out.. writing to standard out anyway" echo "${LOG_LASTLINE}" fi exit 1 else exit 0 fi } installkeyat(){ [ -n "${RSYNC_USER}" ] || missing_var "RSYNC_USER" if [ "${RSYNC_USER}" == "root" ];then RSYNC_HOME="/${RSYNC_USER}" else RSYNC_HOME="/home/${RSYNC_USER}" fi [ -d "/root/.ssh" ] || ${CMD_MKDIR} -p /root/.ssh [ -f "/root/.ssh/id_dsa.pub" ] || ssh-keygen -t dsa -f /root/.ssh/id_dsa ${CMD_CAT} /root/.ssh/id_dsa.pub | ssh ${RSYNC_USER}@${1} "if [ ! -d ~${RSYNC_USER}/.ssh ];then mkdir -p ~${RSYNC_USER}/.ssh ; fi && if [ ! -f ~${RSYNC_USER}/.ssh/authorized_keys2 ];then touch ~${RSYNC_USER}/.ssh/authorized_keys2 ; fi && sh -c 'cat - >> ~${RSYNC_USER}/.ssh/authorized_keys2 && chmod 600 ~${RSYNC_USER}/.ssh/authorized_keys2'" } commands_exist(){ MODE="${1}" # check if rm is available CMD_RM=$(which "rm") [ -n "${CMD_RM}" ] && [ -x ${CMD_RM} ] || missing_cmd "rm" "coreutils" "${MODE}" # check if chmod is available CMD_CHMOD=$(which "chmod") [ -n "${CMD_CHMOD}" ] && [ -x ${CMD_CHMOD} ] || missing_cmd "chmod" "coreutils" "${MODE}" # check if mv is available CMD_MV=$(which "mv") [ -n "${CMD_MV}" ] && [ -x ${CMD_MV} ] || missing_cmd "mv" "coreutils" "${MODE}" # check if nano is available CMD_NANO=$(which "nano") [ -n "${CMD_NANO}" ] && [ -x ${CMD_NANO} ] || missing_cmd "nano" "nano" "${MODE}" # check if clear is available CMD_CLEAR=$(which "clear") [ -n "${CMD_CLEAR}" ] && [ -x ${CMD_CLEAR} ] || missing_cmd "clear" "ncurses-bin" "${MODE}" # check if pgrep is available CMD_PGREP=$(which "pgrep") [ -n "${CMD_PGREP}" ] && [ -x ${CMD_PGREP} ] || missing_cmd "pgrep" "procps" "${MODE}" # check if mkdir is available CMD_MKDIR=$(which "mkdir") [ -n "${CMD_MKDIR}" ] && [ -x ${CMD_MKDIR} ] || missing_cmd "mkdir" "coreutils" "${MODE}" # check if tail is available CMD_TAIL=$(which "tail") [ -n "${CMD_TAIL}" ] && [ -x ${CMD_TAIL} ] || missing_cmd "tail" "coreutils" "${MODE}" # check if date is available CMD_DATE=$(which "date") [ -n "${CMD_DATE}" ] && [ -x ${CMD_DATE} ] || missing_cmd "date" "coreutils" "${MODE}" # check if head is available CMD_HEAD=$(which "head") [ -n "${CMD_HEAD}" ] && [ -x ${CMD_HEAD} ] || missing_cmd "head" "coreutils" "${MODE}" # check if tr is available CMD_TR=$(which "tr") [ -n "${CMD_TR}" ] && [ -x ${CMD_TR} ] || missing_cmd "tr" "coreutils" "${MODE}" # check if pwd is available CMD_PWD=$(which "pwd") [ -n "${CMD_PWD}" ] && [ -x ${CMD_PWD} ] || missing_cmd "pwd" "coreutils" "${MODE}" # check if dirname is available CMD_DIRNAME=$(which "dirname") [ -n "${CMD_DIRNAME}" ] && [ -x ${CMD_DIRNAME} ] || missing_cmd "dirname" "coreutils" "${MODE}" # check if expr is available CMD_EXPR=$(which "expr") [ -n "${CMD_EXPR}" ] && [ -x ${CMD_EXPR} ] || missing_cmd "expr" "coreutils" "${MODE}" # check if du is available CMD_DU=$(which "du") [ -n "${CMD_DU}" ] && [ -x ${CMD_DU} ] || missing_cmd "du" "coreutils" "${MODE}" # check if df is available CMD_DF=$(which "df") [ -n "${CMD_DF}" ] && [ -x ${CMD_DF} ] || missing_cmd "df" "coreutils" "${MODE}" # check if cut is available CMD_CUT=$(which "cut") [ -n "${CMD_CUT}" ] && [ -x ${CMD_CUT} ] || missing_cmd "cut" "coreutils" "${MODE}" # check if cat is available CMD_CAT=$(which "cat") [ -n "${CMD_CAT}" ] && [ -x ${CMD_CAT} ] || missing_cmd "cat" "coreutils" "${MODE}" # check if gawk is available CMD_GAWK=$(which "gawk") [ -n "${CMD_GAWK}" ] && [ -x ${CMD_GAWK} ] || missing_cmd "gawk" "gawk" "${MODE}" # NOT NECESSARY:::only check if apt-get is available CMD_APTITUDE=$(which "aptitude") # check if dialog is available CMD_DIALOG=$(which "dialog") [ -n "${CMD_DIALOG}" ] && [ -x ${CMD_DIALOG} ] || missing_cmd "dialog" "dialog" "${MODE}" # check if bc is available CMD_BC=$(which "bc") [ -n "${CMD_BC}" ] && [ -x ${CMD_BC} ] || missing_cmd "bc" "bc" "${MODE}" # check if sed is available CMD_SED=$(which "sed") [ -n "${CMD_SED}" ] && [ -x ${CMD_SED} ] || missing_cmd "sed" "sed" "${MODE}" # check if grep is available CMD_GREP=$(which "grep") [ -n "${CMD_GREP}" ] && [ -x ${CMD_GREP} ] || missing_cmd "grep" "grep" "${MODE}" # check if wget is available CMD_WGET=$(which "wget") [ -n "${CMD_WGET}" ] && [ -x ${CMD_WGET} ] || missing_cmd "wget" "wget" "${MODE}" # check if crontab is available CMD_CRONTAB=$(which "crontab") [ -n "${CMD_CRONTAB}" ] && [ -x ${CMD_CRONTAB} ] || missing_cmd "crontab" "cron" "${MODE}" # check if tar is available CMD_TAR=$(which "tar") [ -n "${CMD_TAR}" ] && [ -x ${CMD_TAR} ] || missing_cmd "tar" "tar" "${MODE}" # check if bzip2 is available CMD_BZIP2=$(which "bzip2") [ -n "${CMD_BZIP2}" ] && [ -x ${CMD_BZIP2} ] || missing_cmd "bzip2" "bzip2" "${MODE}" # MAIL CHECKS if [ "${MAIL_ENABLED}" == 1 ] || [ "${MODE}" == "install" ]; then # check if mail is available CMD_MAIL=$(which "mail") [ -n "${CMD_MAIL}" ] && [ -x ${CMD_MAIL} ] || missing_cmd "mail" "mailx" "${MODE}" fi # SY CHECKS if [ "${SY_ENABLED}" == 1 ] || [ "${MODE}" == "install" ]; then # check if dpkg is available CMD_DPKG=$(which "dpkg") [ -n "${CMD_DPKG}" ] && [ -x ${CMD_DPKG} ] || missing_cmd "dpkg" "dpkg" "${MODE}" # NOT NECESSARY:::only check if pear is available CMD_PEAR=$(which "pear") fi # DB CHECKS if [ "${DB_ENABLED}" == 1 ] || [ "${MODE}" == "install" ]; then # check if mysqldump is available CMD_MYSQLDUMP=$(which "mysqldump") [ -n "${CMD_MYSQLDUMP}" ] && [ -x ${CMD_MYSQLDUMP} ] || missing_cmd "mysqldump" "mysql-client" "${MODE}" CMD_MYSQL=$(which "mysql") [ -n "${CMD_MYSQL}" ] && [ -x ${CMD_MYSQL} ] || missing_cmd "mysql" "mysql-client" "${MODE}" fi # MCRYPT CHECKS if [ "${ENCRYPTION_ENABLED}" == 1 ] || [ "${MODE}" == "install" ]; then # check if mcrypt is available CMD_OPENSSL=$(which "openssl") [ -n "${CMD_OPENSSL}" ] && [ -x ${CMD_OPENSSL} ] || missing_cmd "openssl" "openssl" "${MODE}" fi # FTP CHECKS if [ "${FTP_ENABLED}" == 1 ] || [ "${MODE}" == "install" ]; then # check if the ftp-upload is available CMD_FTPUPLOAD=$(which "ftp-upload") [ -n "${CMD_FTPUPLOAD}" ] && [ -x ${CMD_FTPUPLOAD} ] || missing_cmd "ftp-upload" "ftp-upload" "${MODE}" fi # RSYNC CHECKS if [ "${RSYNC_ENABLED}" == 1 ] || [ "${MODE}" == "install" ]; then # check if the ftp-upload is available CMD_RSYNC=$(which "rsync") [ -n "${CMD_RSYNC}" ] && [ -x ${CMD_RSYNC} ] || missing_cmd "rsync" "rsync" "${MODE}" fi } fetch_account(){ ${CMD_WGET} -q -O- "${APP_ACNTHTTP}&PROT=${1}" > ${APP_ACNTFILE} if [ $? -eq 0 ]; then ${CMD_CHMOD} 744 ${APP_ACNTFILE} source ${APP_ACNTFILE} else logit "warning: unable to fetch account data" fi } config_load(){ # load settings or create settings file if [ -f "${APP_CONFFILE}" ]; then source ${APP_CONFFILE} else if [ "${1}" != "only_try" ];then logit "fatal: no config file: ${APP_CONFFILE}, run ${0} install" fi fi } config_setup(){ # config file defaults & dialogs [ -n "${FS_SOUREDIRS}" ] || FS_SOUREDIRS="/etc /home /root /var /www" [ -n "${FS_DESTINDIR}" ] || FS_DESTINDIR="/tmp/${APP_BASENAME}_archive" if [ -f "/etc/mysql/debian.cnf" ];then [ -n "${DB_ENABLED}" ] || DB_ENABLED=1 [ -n "${DB_USER}" ] || DB_USER=$(${CMD_CAT} /etc/mysql/debian.cnf |${CMD_GREP} 'user' |${CMD_HEAD} -n1 |${CMD_GAWK} '{print $3}') [ -n "${DB_PASS}" ] || DB_PASS=$(${CMD_CAT} /etc/mysql/debian.cnf |${CMD_GREP} 'password' |${CMD_HEAD} -n1 |${CMD_GAWK} '{print $3}') [ -n "${DB_HOST}" ] || DB_HOST="localhost" else DB_ENABLED=0 fi [ -n "${SY_ENABLED}" ] || SY_ENABLED=1 [ -n "${TAR_EXCLUDE}" ] || TAR_EXCLUDE="" [ -n "${GZIP_ENABLED}" ] || GZIP_ENABLED=1 [ -n "${ENCRYPTION_ENABLED}" ] || ENCRYPTION_ENABLED=0 [ -n "${ENCRYPTION_PASS}" ] || ENCRYPTION_PASS="" [ -n "${FTP_ENABLED}" ] || FTP_ENABLED=1 [ -n "${FTP_HOST}" ] || FTP_HOST="storage01.true.nl" [ -n "${FTP_USER}" ] || FTP_USER="" [ -n "${FTP_PASS}" ] || FTP_PASS="" [ -n "${FTP_CDIR}" ] || FTP_CDIR="/" [ -n "${FTP_CLEANUPAFTERUPLOAD}" ] || FTP_CLEANUPAFTERUPLOAD=1 [ -n "${RSYNC_ENABLED}" ] || RSYNC_ENABLED=0 [ -n "${RSYNC_HOST}" ] || RSYNC_HOST="slurpssh.true.nl" [ -n "${RSYNC_USER}" ] || RSYNC_USER="root" [ -n "${RSYNC_PASS}" ] || RSYNC_PASS="" [ -n "${RSYNC_CDIR}" ] || RSYNC_CDIR="" [ -n "${LOG_ENABLED}" ] || LOG_ENABLED=1 [ -n "${LOG_FILE}" ] || LOG_FILE="/var/log/ksecure_backup.log" [ -n "${OUTPUT_ENABLED}" ] || OUTPUT_ENABLED=0 [ -n "${OUTPUT_DEBUGENABLED}" ] || OUTPUT_DEBUGENABLED=0 [ -n "${MAIL_ENABLED}" ] || MAIL_ENABLED=1 [ -n "${MAIL_TO}" ] || MAIL_TO="" # DIALOGS dia_Input "Filesystem" "Space separated list of directories that I should backup" "${FS_SOUREDIRS}" FS_SOUREDIRS="${dia_ret}" dia_YesNo "Compression" "Do you want to gzip the tar archives (slower, but smaller files)?" GZIP_ENABLED=${dia_ret} dia_Select "Upload" "What method should I use for uploading the backup files?" "FTP" "RSYNC" if [ "${dia_ret}" == "RSYNC" ];then RSYNC_ENABLED=1 dia_Input "RSYNC Upload" "hostname" "${RSYNC_HOST}" RSYNC_HOST="${dia_ret}" if [ "${RSYNC_HOST}" == "slurpssh.true.nl" ];then # try to fetch account data from storage server dia_YesNo "Fetch accountdata" "Do you want to try to download the account settings from this server?" FETCH_ACCOUNT=${dia_ret} if [ "${FETCH_ACCOUNT}" == 1 ];then fetch_account "RSYNC" fi fi dia_Input "RSYNC Upload" "username" "${RSYNC_USER}" RSYNC_USER="${dia_ret}" dia_Input "RSYNC Upload" "password" "${RSYNC_PASS}" RSYNC_PASS="${dia_ret}" dia_Input "RSYNC Upload" "remote directory" "${RSYNC_CDIR}" RSYNC_CDIR="${dia_ret}" FTP_ENABLED=0 FTP_USER="" FTP_PASS="" FTP_HOST="" FTP_CDIR="" else FTP_ENABLED=1 dia_Input "FTP Upload" "hostname" "${FTP_HOST}" FTP_HOST="${dia_ret}" if [ "${FTP_HOST}" == "storage01.true.nl" ];then # try to fetch account data from storage server dia_YesNo "Fetch accountdata" "Do you want to try to download the account settings from this server?" FETCH_ACCOUNT=${dia_ret} if [ "${FETCH_ACCOUNT}" == 1 ];then fetch_account "FTP" fi fi dia_Input "FTP Upload" "username" "${FTP_USER}" FTP_USER="${dia_ret}" dia_Input "FTP Upload" "password" "${FTP_PASS}" FTP_PASS="${dia_ret}" RSYNC_ENABLED=0 RSYNC_USER="" RSYNC_PASS="" RSYNC_HOST="" RSYNC_CDIR="" fi dia_YesNo "Crontab" "Do you want to schedule the script (check for updates @ 23h, run backup @ 01h)?" ADD_BACKUP_TO_CRON=${dia_ret} if [ "${ADD_BACKUP_TO_CRON}" -eq 1 ];then ${CMD_CRONTAB} -l | ${CMD_GREP} -v "ksecure_backup" > /tmp/ksec_back_fichier.tmp echo "00 23 * * * ${APP_FULLPATH} upgrade" >> /tmp/ksec_back_fichier.tmp echo "00 01 * * * ${APP_FULLPATH}" >> /tmp/ksec_back_fichier.tmp ${CMD_CRONTAB} /tmp/ksec_back_fichier.tmp fi dia_Input "Notification" "What is the email-address I should send warnings to?" "${MAIL_TO}" MAIL_TO=${dia_ret} # write config file echo "# The settings below can be adjusted to change the behaviour of the backup FS_SOUREDIRS=\"${FS_SOUREDIRS}\" FS_DESTINDIR=\"${FS_DESTINDIR}\" # whether to backup all databases (on debian, account settings can be automatically discovered) DB_ENABLED=${DB_ENABLED} DB_USER=\"${DB_USER}\" DB_PASS=\"${DB_PASS}\" DB_HOST=\"${DB_HOST}\" # whether to backup a list of crontab, installed apt+pear packages (debian only) SY_ENABLED=${SY_ENABLED} # exlude pattern from archive TAR_EXCLUDE="${TAR_EXCLUDE}" # whether to compress the tar archives GZIP_ENABLED=${GZIP_ENABLED} # whether to encrypt all the data using a password # files may be unencrypted using: # openssl enc -d -aes-256-cbc -in foobar.tar.gz.enc -out foobar.tar.gz ENCRYPTION_ENABLED=${ENCRYPTION_ENABLED} ENCRYPTION_PASS=\"${ENCRYPTION_PASS}\" # whether to upload the data to a server using ftp (instead of rsync!) FTP_ENABLED=${FTP_ENABLED} FTP_HOST=\"${FTP_HOST}\" FTP_USER=\"${FTP_USER}\" FTP_PASS=\"${FTP_PASS}\" FTP_CDIR=\"${FTP_CDIR}\" FTP_CLEANUPAFTERUPLOAD=${FTP_CLEANUPAFTERUPLOAD} # whether to upload the data to a server using rsync (instead of ftp!) RSYNC_ENABLED=${RSYNC_ENABLED} RSYNC_HOST=\"${RSYNC_HOST}\" RSYNC_USER=\"${RSYNC_USER}\" RSYNC_PASS=\"${RSYNC_PASS}\" RSYNC_CDIR=\"${RSYNC_CDIR}\" # whether to log to a file LOG_ENABLED=${LOG_ENABLED} LOG_FILE=\"${LOG_FILE}\" # whether to print to the standard output (on screen) # otherwise all info will be in the logfile, except for installation+config dialogs OUTPUT_ENABLED=${OUTPUT_ENABLED} OUTPUT_DEBUGENABLED=${OUTPUT_DEBUGENABLED} # whether to mail warnings MAIL_ENABLED=${MAIL_ENABLED} MAIL_TO=\"${MAIL_TO}\"" > ${APP_CONFFILE} # let the user review the file with nano dia_YesNo "Configuration file" "Do you want to review the config file to make some final adjustments?" VIEW_CONFIG=${dia_ret} if [ "${VIEW_CONFIG}" == 1 ];then ${CMD_NANO} ${APP_CONFFILE} fi ${CMD_CLEAR} echo "" if [ "${ADD_BACKUP_TO_CRON}" == 1 ];then echo "Crontab updated"; fi echo "Configfile written to ${APP_CONFFILE}"; echo "" usage exit 0 } usage(){ echo "Usage ${APP_BASEEXEC} [command]" echo "" echo "${APP_HUMNNAME} is a simple backup utility. " echo "Use it to backup your internet server." echo "" echo "Commands:" echo " config - Reconfigure the settings" echo " install - Install all the prerequisites (packages & ssh keys is nesessary)" echo " upgrade - Upgrade this script" echo " backup - Run backup procedure" echo " help - This page" echo "" echo " This ${APP_HUMNNAME} has Super-God Masterforce Powers." } ########################################################################## # application defaults and init # ########################################################################## # PRE-INITIALIZE THE COMMANDS WE CAN FIND, WITHOUR REPORTING ANY ERRORS commands_exist "init" # FIGURE OUT FULL PATH CURRENT_DIR="$(${CMD_PWD})" progdir="$(dirname ${0})" cd $progdir APP_DIRENAME="$(${CMD_PWD})" APP_FULLPATH="${APP_DIRENAME}/$(basename ${0})" cd ${CURRENT_DIR} # APP DEFAULTS [ -n "${APP_HUMNNAME}" ] || APP_HUMNNAME="kSecure Backup" [ -n "${APP_BASEEXEC}" ] || APP_BASEEXEC=$(basename ${0}) [ -n "${APP_BASENAME}" ] || APP_BASENAME=${APP_BASEEXEC%.[^.]*} [ -n "${APP_HOSTNAME}" ] || APP_HOSTNAME=$(${CMD_CAT} /etc/hostname) [ -n "${APP_CONFFILE}" ] || APP_CONFFILE=$(echo ${APP_FULLPATH} |${CMD_SED} "s#${APP_BASENAME}#${APP_BASENAME}.conf#g") [ -n "${APP_UPDTFILE}" ] || APP_UPDTFILE=$(echo ${APP_FULLPATH} |${CMD_SED} "s#${APP_BASENAME}#${APP_BASENAME}.updt#g") [ -n "${APP_ACNTFILE}" ] || APP_ACNTFILE=$(echo ${APP_FULLPATH} |${CMD_SED} "s#${APP_BASENAME}#${APP_BASENAME}.acnt#g") [ -n "${APP_UPDTHTTP}" ] || APP_UPDTHTTP="http://kevin.vanzonneveld.net/items/code/ksecure_backup.bash" [ -n "${APP_ACNTHTTP}" ] || APP_ACNTHTTP="http://storage01.true.nl/account.php?md5=f8fbd954801ae6798f6c31a48893091e" # LOG DEFAULTS (Do this quickly, so everything else can make use of the log!) #if [ "${LOG_ENABLED}" == 1 ]; then # default logfile [ -n "${LOG_FILE}" ] || LOG_FILE="/var/log/${APP_BASENAME}.log" # cleanup logfile echo -n "" > $LOG_FILE #fi # create tempfile for dialog output tempfile=`tempfile 2>/dev/null` || tempfile=/tmp/test$$ trap "rm -f $tempfile" 0 1 2 5 15 ########################################################################## # different runmodes # ########################################################################## if [ "${1}" == "install" ];then logit "info: initiating install procedure" # check if the nescessary commands exist commands_exist "install" [ -f "${APP_CONFFILE}" ] || config_setup config_load if [ -n "${RSYNC_HOST}" ];then dia_YesNo "Rsync" "Do you want to try to automatically install an SSH key at ${RSYNC_HOST}?" INSTALL=${dia_ret} if [ "${INSTALL}" == 1 ]; then installkeyat ${RSYNC_HOST} fi fi logit "info: install procedure finished. if no errors occured you can run ${APP_FULLPATH} to start the backup procedure" echo "done" quit elif [ "${1}" == "upgrade" ];then logit "info: initiating upgrade procedure" # check if the nescessary commands exist commands_exist "run" config_load ${CMD_WGET} -q -O- "${APP_UPDTHTTP}" > ${APP_UPDTFILE} if [ $? -ne 0 ]; then logit "fatal: could not download upgrade" else ${CMD_CHMOD} 744 ${APP_UPDTFILE} if [ $? -ne 0 ]; then logit "fatal: could not chmod the downloaded upgrade" fi # successful download APP_CRNTVERS=$(${CMD_HEAD} -n35 ${APP_FULLPATH} |${CMD_GREP} '@version' |${CMD_GAWK} '{print $NF}') APP_UPDTVERS=$(${CMD_HEAD} -n35 ${APP_UPDTFILE} |${CMD_GREP} '@version' |${CMD_GAWK} '{print $NF}') # validate parsed version [ -n "${APP_CRNTVERS}" ] || logit "fatal: cannot determine current app version '${APP_CRNTVERS}'" [ -n "${APP_UPDTVERS}" ] || logit "fatal: cannot determine current app version '${APP_UPDTVERS}'" APP_CRNTVERS_CALC=$(echo "${APP_CRNTVERS} * 1000" |${CMD_BC} |${CMD_GAWK} -F'.' '{print $1}') APP_UPDTVERS_CALC=$(echo "${APP_UPDTVERS} * 1000" |${CMD_BC} |${CMD_GAWK} -F'.' '{print $1}') # is the new version higher? logit "debug: current: ${APP_CRNTVERS} (calc ${APP_CRNTVERS_CALC})" logit "debug: update: ${APP_UPDTVERS} (calc ${APP_UPDTVERS_CALC})" # validate calculated version [ -n "${APP_CRNTVERS_CALC}" ] || logit "fatal: cannot calculate current app version '${APP_CRNTVERS_CALC}'" [ -n "${APP_UPDTVERS_CALC}" ] || logit "fatal: cannot calculate current app version '${APP_UPDTVERS_CALC}'" # is the download version newer ? if [ "${APP_UPDTVERS_CALC}" -gt "${APP_CRNTVERS_CALC}" ];then logit "info: a new version is remotely available, upgrading.." ${CMD_MV} -f ${APP_UPDTFILE} ${APP_FULLPATH} # unable to replace script if [ $? -ne 0 ]; then logit "fatal: could move updated version to current version" # remove update file ${CMD_RM} -f ${APP_UPDTFILE} else logit "info: upgrade successful" echo "upgrade successful, more info in ${LOG_FILE}" fi else logit "info: no new version available, no need to upgrade" # remove update file ${CMD_RM} -f ${APP_UPDTFILE} fi fi quit elif [ "${1}" == "config" ];then logit "info: initiating config procedure" # check if the nescessary commands exist commands_exist "run" config_load "only_try" config_setup quit elif [ "${1}" == "help" ];then logit "info: initiating help procedure" # check if the nescessary commands exist commands_exist "run" usage quit elif [ "${1}" == "" ] || [ "${1}" == "backup" ];then logit "info: initiating normal backup procedure" # check if the nescessary commands exist config_load commands_exist "run" # do not quit, so we can continue else logit "critical: unknown command. please review the help" usage quit fi ########################################################################## # Proceed with normal backup runmode # ########################################################################## ########################################################################## # reconfigure some settings # ########################################################################## # TAR DEFAULTS if [ -n "${TAR_EXCLUDE}" ]; then TAR_EXCLUDE_X_TAR="--exclude=${TAR_EXCLUDE}" else TAR_EXCLUDE_X_TAR="" fi # GZIP DEFAULTS if [ "${GZIP_ENABLED}" == 1 ]; then GZIP_ENABLED_X_EXT=".gz" GZIP_ENABLED_X_TAR="z" else GZIP_ENABLED_X_EXT="" GZIP_ENABLED_X_TAR="" fi # determine date string (first of the month should be saved separately) if [ $(${CMD_DATE} '+%d') == 1 ]; then MONTHNAME=$(${CMD_DATE} '+%B'| ${CMD_TR} "[:upper:]" "[:lower:]") DATESTR="$(${CMD_DATE} '+%Y-m%m'| ${CMD_TR} "[:upper:]" "[:lower:]")-${MONTHNAME:0:3}" else WEEKDAY=$(${CMD_DATE} '+%A'| ${CMD_TR} "[:upper:]" "[:lower:]") DATESTR="d0$(${CMD_DATE} '+%w')-${WEEKDAY:0:3}" fi ########################################################################## # error handling # ########################################################################## # APP CHECKS [ -n "${APP_BASENAME}" ] || missing_var "APP_BASENAME" [ -n "${APP_HOSTNAME}" ] || missing_var "APP_HOSTNAME" # LOG CHECKS if [ "${LOG_ENABLED}" == 1 ]; then # check variables [ -n "${LOG_FILE}" ] || missing_var "LOG_FILE" fi # MAIL CHECKS if [ "${MAIL_ENABLED}" == 1 ]; then # check if mail is available [ -n "${MAIL_TO}" ] || missing_var "MAIL_TO" fi # FS CHECKS if [ ! -d "${FS_DESTINDIR}" ]; then # backup storage directory does not exist logit "warning: ${FS_DESTINDIR} does not exist, trying to create" ${CMD_MKDIR} -p ${FS_DESTINDIR} 2> /dev/null if [ ! -d "${FS_DESTINDIR}" ]; then logit "fatal: ${FS_DESTINDIR} still does not exist, unable to create it" fi fi if [ $(${CMD_DF} -kP ${FS_DESTINDIR} | ${CMD_GAWK} '{print $4}' | $CMD_GREP '[0-9]') -lt 3000000 ]; then # backup storage directory does not contain enough free space logit "fatal: ${FS_DESTINDIR} does not contain enough free space, I need at least 3GB to store temporary files" fi # DB CHECKS if [ "${DB_ENABLED}" == 1 ]; then # check variables [ -n "${DB_USER}" ] || missing_var "DB_USER" [ -n "${DB_PASS}"