#!@BASH@
+# -*- mode: sh; sh-basic-offset: 3; indent-tabs-mode: nil; -*-
+#
# |\_
# B A C K U P N I N J A /()/
# `\|
#####################################################
## FUNCTIONS
-setupcolors () {
+function setupcolors () {
BLUE="\033[34;01m"
GREEN="\033[32;01m"
YELLOW="\033[33;01m"
RED="\033[31;01m"
OFF="\033[0m"
CYAN="\033[36;01m"
+ COLORS=($BLUE $GREEN $YELLOW $RED $PURPLE)
}
-colorize () {
+function colorize () {
if [ "$usecolors" == "yes" ]; then
- local typestr=`echo "$@" | sed 's/\(^[^:]*\).*$/\1/'`
- [ "$typestr" == "Debug" ] && COLOR=$BLUE
- [ "$typestr" == "Info" ] && COLOR=$GREEN
- [ "$typestr" == "Warning" ] && COLOR=$YELLOW
- [ "$typestr" == "Error" ] && COLOR=$RED
- [ "$typestr" == "Fatal" ] && COLOR=$PURPLE
+ local typestr=`echo "$@" | @SED@ 's/\(^[^:]*\).*$/\1/'`
+ [ "$typestr" == "Debug" ] && type=0
+ [ "$typestr" == "Info" ] && type=1
+ [ "$typestr" == "Warning" ] && type=2
+ [ "$typestr" == "Error" ] && type=3
+ [ "$typestr" == "Fatal" ] && type=4
+ color=${COLORS[$type]}
endcolor=$OFF
- echo -e "$COLOR$@$endcolor"
+ echo -e "$color$@$endcolor"
else
echo -e "$@"
fi
type=$1
shift
if [ $type == 100 ]; then
- typestr=`echo "$@" | sed 's/\(^[^:]*\).*$/\1/'`
+ typestr=`echo "$@" | @SED@ 's/\(^[^:]*\).*$/\1/'`
[ "$typestr" == "Debug" ] && type=0
[ "$typestr" == "Info" ] && type=1
[ "$typestr" == "Warning" ] && type=2
let "msgcount += 1"
}
-function setfile() {
- CURRENT_CONF_FILE=$1
-}
-
-function setsection() {
- CURRENT_SECTION=$1
-}
-
-
-#
-# sets a global var with name equal to $1
-# to the value of the configuration parameter $1
-# $2 is the default.
-#
-
-function getconf() {
- CURRENT_PARAM=$1
- ret=`awk -f $scriptdir/parseini S=$CURRENT_SECTION P=$CURRENT_PARAM $CURRENT_CONF_FILE`
- # if nothing is returned, set the default
- if [ "$ret" == "" -a "$2" != "" ]; then
- ret="$2"
- fi
-
- # replace * with %, so that it is not globbed.
- ret="${ret//\\*/__star__}"
-
- # this is weird, but single quotes are needed to
- # allow for returned values with spaces. $ret is still expanded
- # because it is in an 'eval' statement.
- eval $1='$ret'
-}
-
#
# enforces very strict permissions on configuration file $file.
#
function check_perms() {
- local file=$1
- local perms=`ls -ld $file`
- perms=${perms:4:6}
- if [ "$perms" != "------" ]; then
- echo "Configuration files must not be group or world writable/readable! Dying on file $file"
- fatal "Configuration files must not be group or world writable/readable! Dying on file $file"
- fi
- if [ `ls -ld $file | awk '{print $3}'` != "root" ]; then
- echo "Configuration files must be owned by root! Dying on file $file"
- fatal "Configuration files must be owned by root! Dying on file $file"
- fi
+ local file=$1
+ debug "check_perms $file"
+ local perms
+ local owners
+
+ perms=($(stat -L --format='%A' $file))
+ debug "perms: $perms"
+ local gperm=${perms:4:3}
+ debug "gperm: $gperm"
+ local wperm=${perms:7:3}
+ debug "wperm: $wperm"
+
+ owners=($(stat -L --format='%g %G %u %U' $file))
+ local gid=${owners[0]}
+ local group=${owners[1]}
+ local owner=${owners[2]}
+
+ if [ "$owner" != 0 ]; then
+ echo "Configuration files must be owned by root! Dying on file $file"
+ fatal "Configuration files must be owned by root! Dying on file $file"
+ fi
+
+ if [ "$wperm" != '---' ]; then
+ echo "Configuration files must not be world writable/readable! Dying on file $file"
+ fatal "Configuration files must not be world writable/readable! Dying on file $file"
+ fi
+
+ if [ "$gperm" != '---' ]; then
+ case "$admingroup" in
+ $gid|$group) :;;
+
+ *)
+ if [ "$gid" != 0 ]; then
+ echo "Configuration files must not be writable/readable by group $group! Use the admingroup option in backupninja.conf. Dying on file $file"
+ fatal "Configuration files must not be writable/readable by group $group! Use the admingroup option in backupninja.conf. Dying on file $file"
+ fi
+ ;;
+ esac
+ fi
}
# simple lowercase function
# simple to integer function
function toint() {
- echo "$1" | tr [:alpha:] -d
+ echo "$1" | tr -d '[:alpha:]'
}
#
whendayofweek=$1; at=$2; whentime=$3;
whenday=`toint "$whendayofweek"`
whendayofweek=`tolower "$whendayofweek"`
- whentime=`echo "$whentime" | sed 's/:[0-9][0-9]$//' | sed -r 's/^([0-9])$/0\1/'`
+ whentime=`echo "$whentime" | @SED@ 's/:[0-9][0-9]$//' | @SED@ -r 's/^([0-9])$/0\1/'`
if [ "$whendayofweek" == "everyday" -o "$whendayofweek" == "daily" ]; then
whendayofweek=$nowdayofweek
echo "" > $bufferfile
echo_debug_msg=1
(
- . $scriptdir/$suffix $file
+ . $scriptdirectory/$suffix $file
) 2>&1 | (
while read a; do
echo $a >> $bufferfile
fatal "Configuration file $conffile not found."
fi
-# find $scriptdir
-scriptdir=`grep scriptdirectory $conffile | awk '{print $3}'`
-if [ -z "$scriptdir" ]; then
- if [ -d "@datadir@" ]; then
- scriptdir="@datadir@"
- else
- echo "Could not find entry 'scriptdirectory' in $conffile"
- fatal "Could not find entry 'scriptdirectory' in $conffile"
- fi
-else
- if [ ! -d "$scriptdir" ]; then
- echo "Script directory $scriptdir not found."
- fatal "Script directory $scriptdir not found."
- fi
-fi
-
-# find $libdir
-libdir=`grep libdirectory $conffile | awk '{print $3}'`
-if [ -z "$libdir" ]; then
+# find $libdirectory
+libdirectory=`grep '^libdirectory' $conffile | @AWK@ '{print $3}'`
+if [ -z "$libdirectory" ]; then
if [ -d "@libdir@" ]; then
- libdir="@libdir@"
+ libdirectory="@libdir@"
else
echo "Could not find entry 'libdirectory' in $conffile."
fatal "Could not find entry 'libdirectory' in $conffile."
fi
else
- if [ ! -d "$libdir" ]; then
- echo "Lib directory $libdir not found."
- fatal "Lib directory $libdir not found."
+ if [ ! -d "$libdirectory" ]; then
+ echo "Lib directory $libdirectory not found."
+ fatal "Lib directory $libdirectory not found."
fi
fi
+# include shared functions
+. $libdirectory/tools
+. $libdirectory/vserver
+
setfile $conffile
# get global config options (second param is the default)
getconf configdirectory @CFGDIR@/backup.d
+getconf scriptdirectory @datadir@
+getconf reportdirectory
getconf reportemail
+getconf reporthost
+getconf reportspace
getconf reportsuccess yes
+getconf reportuser
getconf reportwarning yes
getconf loglevel 3
getconf when "Everyday at 01:00"
getconf SLAPCAT /usr/sbin/slapcat
getconf LDAPSEARCH /usr/bin/ldapsearch
getconf RDIFFBACKUP /usr/bin/rdiff-backup
+getconf CSTREAM /usr/bin/cstream
+getconf MYSQLADMIN /usr/bin/mysqladmin
getconf MYSQL /usr/bin/mysql
getconf MYSQLHOTCOPY /usr/bin/mysqlhotcopy
getconf MYSQLDUMP /usr/bin/mysqldump
getconf PGSQLDUMP /usr/bin/pg_dump
getconf PGSQLDUMPALL /usr/bin/pg_dumpall
+getconf PGSQLUSER postgres
getconf GZIP /bin/gzip
getconf RSYNC /usr/bin/rsync
-getconf vservers no
-getconf VSERVERINFO /usr/sbin/vserver-info
-getconf VSERVER /usr/sbin/vserver
-getconf VROOTDIR `if [ -f "$VSERVERINFO" ]; then $VSERVERINFO info SYSINFO |grep vserver-Rootdir | awk '{print $2}'; fi`
+getconf admingroup root
+
+# initialize vservers support
+# (get config variables and check real vservers availability)
+init_vservers nodialog
if [ ! -d "$configdirectory" ]; then
echo "Configuration directory '$configdirectory' not found."
fatal "Configuration directory '$configdirectory' not found."
fi
-# include shared functions
-. $libdir/tools
-
[ -f "$logfile" ] || touch $logfile
if [ "$UID" != "0" ]; then
- echo "$0 can only be run as root"
+ echo "`basename $0` can only be run as root"
exit 1
fi
-if [ "$vservers" == "yes" -a ! -d "$VROOTDIR" ]; then
- echo "vservers option set in config, but $VROOTDIR is not a directory!"
- fatal "vservers option set in config, but $VROOTDIR is not a directory!"
-fi
-
## Process each configuration file
# by default, don't make files which are world or group readable.
if [ "$singlerun" ]; then
files=$singlerun
else
- files=`find $configdirectory -mindepth 1 ! -name '.*.swp' | sort -n`
+ files=`find $configdirectory -follow -mindepth 1 -maxdepth 1 -type f ! -name '.*.swp' | sort -n`
+
+ if [ -z "$files" ]; then
+ fatal "No backup actions configured in '$configdirectory', run ninjahelper!"
+ fi
fi
for file in $files; do
[ -f "$file" ] || continue
+ check_perms ${file%/*} # check containing dir
check_perms $file
suffix="${file##*.}"
base=`basename $file`
continue
fi
- if [ -e "$scriptdir/$suffix" ]; then
+ if [ -e "$scriptdirectory/$suffix" ]; then
process_action $file $suffix
else
error "Can't process file '$file': no handler script for suffix '$suffix'"
echo ${messages[$i]}
done
echo -e "$errormsg"
- } | mail $reportemail -s "backupninja: $hostname $subject"
+ if [ "$reportspace" == "yes" ]; then
+ previous=""
+ for i in $(ls "$configdirectory"); do
+ backuploc=$(grep ^directory "$configdirectory"/"$i" | @AWK@ '{print $3}')
+ if [ "$backuploc" != "$previous" ]; then
+ df -h "$backuploc"
+ previous="$backuploc"
+ fi
+ done
+ fi
+ } | mail -s "backupninja: $hostname $subject" $reportemail
fi
if [ $actions_run != 0 ]; then
info "FINISHED: $actions_run actions run. $fatals fatal. $errors error. $warnings warning."
fi
+
+if [ -n "$reporthost" ]; then
+ debug "send $logfile to $reportuser@$reporthost:$reportdirectory"
+ rsync -qt $logfile $reportuser@$reporthost:$reportdirectory
+fi