diff options
-rwxr-xr-x | backupninja | 308 | ||||
-rw-r--r-- | changelog | 6 | ||||
-rw-r--r-- | etc/backupninja.conf | 3 | ||||
-rw-r--r-- | handlers/ldap | 12 | ||||
-rw-r--r-- | handlers/mysql | 38 | ||||
-rw-r--r-- | handlers/rdiff | 26 | ||||
-rwxr-xr-x | handlers/sys | 6 |
7 files changed, 221 insertions, 178 deletions
diff --git a/backupninja b/backupninja index c8764ab..3b3b16d 100755 --- a/backupninja +++ b/backupninja @@ -17,44 +17,34 @@ # ##################################################### -## DEFAULTS - -DEBUG=${DEBUG:=0} -CONFFILE="/etc/backupninja.conf" -USECOLOURS=1 - -##################################################### ## FUNCTIONS function setupcolors() { - if [ "$USECOLOURS" == 1 ] - then - BLUE="\033[34;01m" - GREEN="\033[32;01m" - YELLOW="\033[33;01m" - PURPLE="\033[35;01m" - RED="\033[31;01m" - OFF="\033[0m" - CYAN="\033[36;01m" - fi + BLUE="\033[34;01m" + GREEN="\033[32;01m" + YELLOW="\033[33;01m" + PURPLE="\033[35;01m" + RED="\033[31;01m" + OFF="\033[0m" + CYAN="\033[36;01m" } -function run() { - RUNERROR=0 - debug 0 "$@" - returnstring=`$@ 2>&1` - RUNERROR=$? - RUNERRORS=$[RUNERRORS+RUNERROR] - if [ "$RUNERROR" != 0 ]; then - debug 3 "Exitcode $RUNERROR returned when running: $@" - debug 3 "$returnstring" - else - debug 0 "$returnstring" - fi - return $RUNERROR -} - -# We have the following debug levels: +#function run() { +# RUNERROR=0 +# debug 0 "$@" +# returnstring=`$@ 2>&1` +# RUNERROR=$? +# RUNERRORS=$[RUNERRORS+RUNERROR] +# if [ "$RUNERROR" != 0 ]; then +# debug 3 "Exitcode $RUNERROR returned when running: $@" +# debug 3 "$returnstring" +# else +# debug 0 "$returnstring" +# fi +# return $RUNERROR +#} + +# We have the following message levels: # 0 - debug - blue # 1 - normal messages - green # 2 - warnings - yellow @@ -66,33 +56,52 @@ function run() { # used to capture output from handlers echo_debug_msg=0 -function debug() { +usecolor=yes +function printmsg() { [ ${#@} -gt 1 ] || return - TYPES=(Debug Info Warning Error Fatal) - COLOURS=($BLUE $GREEN $YELLOW $RED $PURPLE) + types=(Debug Info Warning Error Fatal) type=$1 - colour=${COLOURS[$type]} - shift print=$[4-type] - if [ "$print" -lt "$loglevel" -o "$DEBUG" == 1 ]; then - if [ -z "$logfile" ]; then - echo -e "${colour}${TYPES[$type]}: $@${OFF}" >&2 - else - if [ "$DEBUG" == 1 -o "$type" == 4 ]; then - echo -e "${colour}${TYPES[$type]}: $@${OFF}" >&2 - fi - echo -e "${colour}${TYPES[$type]}: $@${OFF}" >> $logfile - fi + typestr=${types[$type]} + if [ "$usecolor" == "yes" ]; then + colors=($BLUE $GREEN $YELLOW $RED $PURPLE) + color=${colors[$type]} + endcolor=$OFF fi + + shift + if [ "$echo_debug_msg" != "0" -a "$type" -gt "1" ]; then - echo -e "${TYPES[$type]}: $@" + echo -e "$typestr: $@" + fi + + if [ "$debug" == 1 ]; then + echo -e "${color}$typestr: $@${endcolor}" >&2 + fi + + if [ "$print" -lt "$loglevel" ]; then + if [ -w "$logfile" ]; then + echo -e "${color}$typestr: $@${endcolor}" >> $logfile + fi fi } +function debug() { + printmsg 0 "$@" +} +function info() { + printmsg 1 "$@" +} +function warning() { + printmsg 2 "$@" +} +function error() { + printmsg 3 "$@" +} function fatal() { - debug 4 "$@" + printmsg 4 "$@" exit 2 } @@ -205,60 +214,120 @@ function isnow() { return 1 } -##################################################### -## MAIN +function usage() { + cat << EOF +$0 usage: +This script allows you to coordinate system backup by dropping a few +simple configuration files into /etc/backup.d/. Typically, this +script is run hourly from cron. -## process command line options +The following options are available: +-h, --help This usage message +-d, --debug Run in debug mode, where all log messages are + output to the current shell. +-f, --conffile FILE Use FILE for the main configuration instead + of /etc/backupninja.conf +-t, --test Run in test mode, no actions are actually taken. +-n, --now Perform actions now, instead of when they + might be scheduled. +When using colored output, there are: +EOF + debug=1 + debug "Debugging info (when run with -d)" + info "Informational messages (verbosity level 4)" + warning "Warnings (verbosity level 3 and up)" + error "Errors (verbosity level 2 and up)" + fatal "Fatal, halting errors (always shown)" +} -if [ "$1" == "--help" ]; then - HELP=1;DEBUG=1;loglevel=4 -else - while getopts h,f:,d,t option - do - case "$option" in - h) HELP=1;DEBUG=1;loglevel=4;; - d) DEBUG=1;loglevel=4;; - f) CONFFILE="$OPTARG";; - t) test=1;DEBUG=1;; - esac - done -fi +function process_action() { + local file="$1" + local suffix="$2" + + setfile $file + + # skip over this config if "when" option + # is not set to the current time. + getconf when "$defaultwhen" + if [ "$processnow" == 1 ]; then + info "running $file because of --now" + else + IFS=$'\t\n' + for w in $when; do + IFS=$' \t\n' + isnow "$w" + ret=$? + IFS=$'\t\n' + if [ $ret == 0 ]; then + debug "skipping $file because it is not $w" + return + else + info "running $file because it is $w" + fi + done + IFS=$' \t\n' + fi -setupcolors + echo_debug_msg=1 + # call the handler: + ret=`( . $scriptdir/$suffix $file )` + retcode="$?" + warnings=`echo $ret | grep -e "^Warning: " | wc -l` + errors=`echo $ret | grep -e "^Error: \|^Fatal: " | wc -l` + if [ $errors != 0 ]; then + msg "*failed* -- $file" + errormsg="$errormsg\n== errors from $file ==\n\n$ret\n" + elif [ $warnings != 0 ]; then + msg "*warning* -- $file" + errormsg="$errormsg\n== warnings from $file ==\n\n$ret\n" + elif [ $retcode == 0 ]; then + msg "success -- $file" + else + msg "unknown -- $file" + fi + echo_debug_msg=0 +} -## Print help +##################################################### +## MAIN -if [ "$HELP" == 1 ]; then -cat << EOF -$0 usage: -This script allows you to coordinate system backup by dropping a few -simple configuration files into /etc/backup.d/. In general, this script -is run from a cron job late at night. +setupcolors +conffile="/etc/backupninja.conf" -The following options are available: --h This help message --d Run in debug mode, where all log messages are output to the current shell. --f <file> Use <file> for the main configuration instead of /etc/backupninja.conf --t Run in test mode, no actions are actually taken. +## process command line options -When using colored output, there are: -EOF -debug 0 "Debugging info (when run with -d)" -debug 1 "Informational messages (verbosity level 4)" -debug 2 "Warnings (verbosity level 3 and up)" -debug 3 "Errors (verbosity level 2 and up)" -debug 4 "Fatal, halting errors (always shown)" -exit 0 -fi +while [ $# -ge 1 ]; do + case $1 in + -h|--help) usage;; + -d|--debug) debug=1;; + -t|--test) test=1;debug=1;; + -n|--now) processnow=1;; + -f|--conffile) + if [ -f $2 ]; then + conffile=$2 + else + fatal "-f|--conffile option must be followed by an existing filename" + usage + fi + # we shift here to avoid processing the file path + shift + ;; + *) + fatal "Unknown option $1" + usage + ;; + esac + shift +done ## Load and confirm basic configuration values # bootstrap -[ -r "$CONFFILE" ] || fatal "Configuration file $CONFFILE not found." -scriptdir=`grep scriptdirectory $CONFFILE | awk '{print $3}'` -[ -n "$scriptdir" ] || fatal "Cound not find entry 'scriptdirectory' in $CONFFILE." +[ -r "$conffile" ] || fatal "Configuration file $conffile not found." +scriptdir=`grep scriptdirectory $conffile | awk '{print $3}'` +[ -n "$scriptdir" ] || fatal "Cound not find entry 'scriptdirectory' in $conffile" [ -d "$scriptdir" ] || fatal "Script directory $scriptdir not found." -setfile $CONFFILE +setfile $conffile # get global config options (second param is the default) getconf configdirectory /etc/backup.d @@ -269,6 +338,7 @@ getconf loglevel 3 getconf when "Everyday at 01:00" defaultwhen=$when getconf logfile /var/log/backupninja.log +getconf usecolors "yes" getconf SLAPCAT /usr/sbin/slapcat getconf RDIFFBACKUP /usr/bin/rdiff-backup getconf MYSQL /usr/bin/mysql @@ -277,11 +347,15 @@ getconf MYSQLDUMP /usr/bin/mysqldump getconf GZIP /bin/gzip [ -d "$configdirectory" ] || fatal "Configuration directory '$configdirectory' not found." -[ `id -u` == "0" ] || fatal "Can only be run as root" + +if [ "$UID" != "0" ]; then + echo "$0 can only be run as root" + exit 1 +fi ## Process each configuration file -debug 1 "====== starting at "`date`" ======" +info "====== starting at "`date`" ======" # by default, don't make files which are world or group readable. umask 077 @@ -295,54 +369,14 @@ for file in $configdirectory/*; do suffix="${file##*.}" base=`basename $file` if [ "${base:0:1}" == "0" ]; then - debug 1 "Skipping $file" + info "Skipping $file" continue - else - debug 1 "Processing $file" fi if [ -e "$scriptdir/$suffix" ]; then - setfile $file - - # skip over this config if "when" option - # is not set to the current time. - getconf when "$defaultwhen" - IFS=$'\t\n' - for w in $when; do - IFS=$' \t\n' - isnow "$w" - ret=$? - IFS=$'\t\n' - if [ $ret == 0 ]; then - debug 0 "skipping $file because it is not $w" - continue - else - debug 0 "running $file because it is $w" - continue - fi - done - IFS=$' \t\n' - - echo_debug_msg=1 - # call the handler: - ret=`( . $scriptdir/$suffix $file )` - retcode="$?" - warnings=`echo $ret | grep -e "^Warning: " | wc -l` - errors=`echo $ret | grep -e "^Error: \|^Fatal: " | wc -l` - if [ $errors != 0 ]; then - msg "*failed* -- $file" - errormsg="$error\n== errors from $file ==\n\n$ret\n" - elif [ $warnings != 0 ]; then - msg "*warning* -- $file" - errormsg="$error\n== warnings from $file ==\n\n$ret\n" - elif [ $retcode == 0 ]; then - msg "success -- $file" - else - msg "unknown -- $file" - fi - echo_debug_msg=0 + process_action $file $suffix else - debug 3 "Can't process file '$file': no handler script for suffix '$suffix'" + error "Can't process file '$file': no handler script for suffix '$suffix'" msg "*missing handler* -- $file" fi done @@ -366,6 +400,6 @@ if [ $doit == 1 ]; then } | mail $reportemail -s "backupninja: $hostname" fi -debug 1 "====== finished at "`date`" ======" +info "====== finished at "`date`" ======" ############################################################ @@ -1,3 +1,9 @@ +version 0.4.1 -- Jan 3 2005 + added $usecolors and now more conservative about when colors are echoed. + fixed major bug, 'when' actually works now. + replaced debug function with debug, info, warning, error, fatal. + added --now option to force all actions to be performed now. + version 0.4 -- Dec 26 2004 added "when" option, so that all configs can specify when they are to be run. diff --git a/etc/backupninja.conf b/etc/backupninja.conf index 45af4ed..1c33830 100644 --- a/etc/backupninja.conf +++ b/etc/backupninja.conf @@ -37,3 +37,6 @@ configdirectory = /etc/backup.d # where backupninja helper scripts are found scriptdirectory = /usr/share/backupninja + +# whether to use colors in the log file +usecolors = yes diff --git a/handlers/ldap b/handlers/ldap index 06e4e28..9ead9d1 100644 --- a/handlers/ldap +++ b/handlers/ldap @@ -47,20 +47,20 @@ if [ "$ldif" == "yes" ]; then fatal "Couldn't create ldif dump file: $dumpdir/$dbsuffix.ldif" fi execstr="$SLAPCAT -f $conf -b $dbsuffix -l $dumpdir/$dbsuffix.ldif" - debug 0 "$execstr" + debug "$execstr" if [ ! $test ]; then output=`$execstr` code=$? if [ "$code" == "0" ]; then - debug 0 $output - debug 1 "Successfully finished ldif export of $dbsuffix" + debug $output + info "Successfully finished ldif export of $dbsuffix" else - debug 2 $output - debug 2 "Failed ldif export of $dbsuffix" + warning $output + warning "Failed ldif export of $dbsuffix" fi if [ "$compress" == "yes" ]; then output=`$GZIP -f "$dumpdir/$dbsuffix.ldif" 2>&1` - debug 0 $output + debug $output fi fi done diff --git a/handlers/mysql b/handlers/mysql index 4439bcc..165ebc6 100644 --- a/handlers/mysql +++ b/handlers/mysql @@ -33,7 +33,7 @@ if [ "$dbusername" != "" ]; then if [ -f $mycnf ]; then # rename temporarily tmpcnf="$home/my.cnf.disable" - debug 0 "mv $mycnf $tmpcnf" + debug "mv $mycnf $tmpcnf" mv $mycnf $tmpcnf fi oldmask=`umask` @@ -60,31 +60,31 @@ fi if [ "$hotcopy" == "yes" ]; then if [ "$databases" == "all" ]; then execstr="$MYSQLHOTCOPY --quiet --allowold --regexp /.\*/./.\*/ $hotdir" - debug 0 "su $user -c '$execstr'" + debug "su $user -c '$execstr'" if [ ! $test ]; then output=`su $user -c "$execstr" 2>&1` code=$? if [ "$code" == "0" ]; then - debug 0 $output - debug 1 "Successfully finished hotcopy of all mysql databases" + debug $output + info "Successfully finished hotcopy of all mysql databases" else - debug 2 $output - debug 2 "Failed to hotcopy all mysql databases" + warning $output + warning "Failed to hotcopy all mysql databases" fi fi else for db in $databases; do execstr="$MYSQLHOTCOPY --allowold $db $hotdir" - debug 0 "su $user -c '$execstr'" + debug "su $user -c '$execstr'" if [ ! $test ]; then output=`su $user -c "$execstr" 2>&1` code=$? if [ "$code" == "0" ]; then - debug 0 $output - debug 1 "Successfully finished hotcopy of mysql database $db" + debug $output + info "Successfully finished hotcopy of mysql database $db" else - debug 2 $output - debug 2 "Failed to hotcopy mysql database $db" + warning $output + warning "Failed to hotcopy mysql database $db" fi fi done @@ -100,32 +100,32 @@ if [ "$sqldump" == "yes" ]; then for db in $databases; do execstr="$MYSQLDUMP --lock-tables --complete-insert --add-drop-table --quick --quote-names $db > $dumpdir/${db}.sql" - debug 0 "su $user -c '$execstr'" + debug "su $user -c '$execstr'" if [ ! $test ]; then output=`su $user -c "$execstr" 2>&1` code=$? if [ "$code" == "0" ]; then - debug 0 $output - debug 1 "Successfully finished dump of mysql database $db" + debug $output + info "Successfully finished dump of mysql database $db" else - debug 2 $output - debug 2 "Failed to dump mysql databases $db" + warning $output + warning "Failed to dump mysql databases $db" fi fi done if [ "$compress" == "yes" ]; then output=`$GZIP -f $dumpdir/*.sql 2>&1` - debug 0 $output + debug $output fi fi if [ "$dbusername" != "" ]; then ## clean up tmp config file - debug 0 "rm $mycnf" + debug "rm $mycnf" rm $mycnf if [ -f "$tmpcnf" ]; then - debug 0 "mv $tmpcnf $mycnf" + debug "mv $tmpcnf $mycnf" mv $tmpcnf $mycnf fi fi diff --git a/handlers/rdiff b/handlers/rdiff index 1f2058f..90ca2a3 100644 --- a/handlers/rdiff +++ b/handlers/rdiff @@ -6,7 +6,7 @@ setsection source getconf type; sourcetype=$type getconf label -getconf user; sourceuser=$user +getconf user root; sourceuser=$user getconf keep getconf include getconf exclude @@ -25,7 +25,7 @@ getconf host; desthost=$host [ "$desttype" == "remote" ] || fatal "Only remote destinations are supported" # see if we can login -debug 0 "su $sourceuser -c \"ssh -o PasswordAuthentication=no $desthost -l $destuser 'echo -n 1'\"" +debug "su $sourceuser -c \"ssh -o PasswordAuthentication=no $desthost -l $destuser 'echo -n 1'\"" if [ ! $test ]; then result=`su $sourceuser -c "ssh -o PasswordAuthentication=no $desthost -l $destuser 'echo -n 1'" 2>&1` if [ "$result" != "1" ]; then @@ -34,7 +34,7 @@ if [ ! $test ]; then fi # see that rdiff-backup has the same version as here -debug 0 "su $sourceuser -c \"ssh $desthost -l $destuser '$RDIFFBACKUP -V'\"" +debug "su $sourceuser -c \"ssh $desthost -l $destuser '$RDIFFBACKUP -V'\"" if [ ! $test ]; then remoteversion=`su $sourceuser -c "ssh $desthost -l $destuser '$RDIFFBACKUP -V'" 2>&1` localversion=`$RDIFFBACKUP -V` @@ -62,16 +62,16 @@ if [ "$keep" -gt "0" ]; then fi removestr="${removestr}${destdir}/${label}"; - debug 0 "su $sourceuser -c '$removestr'" + debug "su $sourceuser -c '$removestr'" if [ ! $test ]; then output=`su $sourceuser -c "$removestr" 2>&1` code=$? if [ "$code" == "0" ]; then - debug 0 $output - debug 1 "Removing backups older than $keep days succeeded." + debug $output + info "Removing backups older than $keep days succeeded." else - debug 2 $output - debug 2 "Failed removing backups older than $keep." + warning $output + warning "Failed removing backups older than $keep." fi fi fi @@ -100,16 +100,16 @@ execstr="${execstr}--exclude '/*' " # include client-part and server-part execstr="${execstr}$execstr_clientpart $execstr_serverpart" -debug 0 "su $sourceuser -c '$execstr'" +debug "su $sourceuser -c '$execstr'" if [ ! $test ]; then output=`su $sourceuser -c "$execstr" 2>&1` code=$? if [ "$code" == "0" ]; then - debug 0 $output - debug 1 "Successfully finished backing up source '$label'" + debug $output + info "Successfully finished backing up source '$label'" else - debug 2 $output - debug 2 "Failed backup up source '$label'" + warning $output + warning "Failed backup up source '$label'" fi fi diff --git a/handlers/sys b/handlers/sys index 35a3919..140db76 100755 --- a/handlers/sys +++ b/handlers/sys @@ -28,21 +28,21 @@ getconf hardwarefile /var/backups/hardware.txt if [ "$packages" == "yes" ]; then if [ ! -x "`which dpkg`" ]; then - debug 2 "can't find dpkg, skipping installed packages report." + warning "can't find dpkg, skipping installed packages report." packages="no" fi fi if [ "$partitions" == "yes" ]; then if [ ! -x "`which sfdisk`" ]; then - debug 2 "can't find sfdisk, skipping partition report." + warning "can't find sfdisk, skipping partition report." partitions="no" fi fi if [ "$hardware" == "yes" ]; then if [ ! -x "`which discover`" ]; then - debug 2 "can't find discover, skipping hardware report." + warning "can't find discover, skipping hardware report." hardware="no" fi fi |