#
# Note: This script relies on GNU tar specific options,
# do not attempt to use it as-is with other tar implementations.
-#
-#
-# Example of use, from crontab
-# # Daily incremental backup
-# 30 3 * * 1-6 /usr/local/bin/brioche > /var/log/backup.`date "+%a"`.log 2>&1
-# # Weekly full backup on Sunday
-# 30 3 * * 0 /usr/local/bin/brioche -f > /var/log/backup.`date "+%a"`.log 2>&1
# Mandatory
SNAPSHOT_SIZE="5G"
USAGE_WARN="80"
-# TODO: Implement the storage on a distant FTP
USE_FTP="no"
-#FTP_HOST="ftpback.example.com"
-#FTP_USER="username"
-#FTP_PASS="password"
-#FTP_KEEP="4"
+FTP_HOST="ftpback.example.com"
+FTP_DIR="/"
+FTP_KEEP="4"
# Ensure that we have a minimal PATH
PATH=/sbin:/bin:/usr/sbin:/usr/bin
echo $@ >> $SUMMARY
}
+# Set final status to CRITICAL
+set_critical()
+{
+ FINAL_STATUS="CRITICAL"
+}
+
+set_error()
+{
+ if [ "$FINAL_STATUS" != "CRITICAL" ]; then
+ FINAL_STATUS="ERROR"
+ fi
+}
+
+set_warning()
+{
+ if [ "$FINAL_STATUS" == "SUCCESS" ]; then
+ FINAL_STATUS="WARNING"
+ fi
+}
+
finish()
{
# Check free space
log "${REPODIR} usage after backup: ${usage}%."
if [ "$usage" -ge "$USAGE_WARN" ]; then
- if [ "$FINAL_STATUS" = "SUCCESS" ]; then
- FINAL_STATUS="WARNING"
- fi
+ set_warning
summary "Warning : Filesystem ${REPODIR} is ${usage}% full."
fi
fi
# Prepare the copy of the snar file
- cp $fullsnar $destsnar
+ cp "$fullsnar" "$destsnar"
# Do the actual backup. Destination file name and snar are like
# /backup/valeron/root.incr.20090105.tar.bz2
# /backup/valeron/root.incr.20090105.snar
log "Running tar..."
- tar -caf ${destfile} ${TAR_OPTS} ${COMPRESS_OPT} -g ${destsnar} $1
+ tar -cf ${destfile} ${TAR_OPTS} ${COMPRESS_OPT} -g ${destsnar} $1
if [ ! "$?" = "0" ]; then
- log "Error $?: Could not archive $hostname - $volumename"
+ log "Error $?: Could not archive $2 - $3"
return 1
fi
return 0
}
+#######################################################################
+# FTP functions
+#######################################################################
+# Push everything in the directory given in $1 to the FTP server, under
+# /FTP_DIR/$2/latest
+ftp_push()
+{
+ log "Mirror $1 on FTP (${FTP_HOST})."
+ local source="${1}"
+ local target="${FTP_DIR}/${2}/latest"
+ local command="mkdir -p ${target}; cd ${target}"
+ command="${command}; mirror --reverse --only-newer --verbose ${source}"
+
+ lftp -e "${command}; exit" ${FTP_HOST}
+}
+
+# Rotate old files on FTP
+# Usage: ftp_rotate group
+ftp_rotate()
+{
+ log "Rotating backups of $1 on FTP (${FTP_HOST})."
+ local lastrun="run-${FTP_KEEP}"
+ local target="${FTP_DIR}/${1}"
+ local commands="mkdir -p ${target}; cd ${target}"
+
+ # Build commands
+ # Remove oldest run
+ if [ "$FTP_KEEP" != "0" ]; then
+ commands="$commands; rmdir ${lastrun}"
+
+ # Move everything back
+ for run in `seq $FTP_KEEP -1 2`; do
+ local newer=$run
+ let "newer -= 1"
+ commands="$commands; mv run-$newer run-$run"
+ done
+ # Move "old latest" to run-1
+ commands="$commands; mv latest run-1"
+ else
+ commands="$commands; rmdir latest"
+ fi
+
+ # Create "new latest" directory
+ commands="$commands; mkdir latest; exit"
+
+ # Run the commands on the FTP server
+ lftp -e "$commands" $FTP_HOST
+}
#######################################################################
# Start here
#######################################################################
source "${CONFIG_FILE}"
else
summary "Error: Unable to read configuration file ${CONFIG_FILE}. Aborting."
- FINAL_STATUS="CRITICAL"
+ set_critical
finish
fi
if [ ! -r "${BACKUPTAB}" ]
then
summary "Error: Unable to read ${BACKUPTAB}. Aborting."
- FINAL_STATUS="CRITICAL"
+ set_critical
finish
fi
# Parse backuptab file, call backup functions for each line
#######################################################################
+# Rotate FTP groups on full
+if [ "$USE_FTP" = "yes" -a "$DO_FULL_BACKUP" = "yes" ]; then
+ for group in `grep -v -E '^[[:space:]]*(#.*)?$' $BACKUPTAB | awk '{print $3}' | sort -u`
+ do
+ ftp_rotate $group
+ done
+fi
+
# Ignore empty and commented lines
grep -v -E '^[[:space:]]*(#.*)?$' $BACKUPTAB | tr -s [:space:]| while read line
do
make_snapshot $vg $lv
if [ "$?" != "0" ]; then
summary "Could not take a snapshot of $device"
- FINAL_STATUS="ERROR"
+ set_error
continue
# Next one
fi
RETVAL="$?"
if [ "$RETVAL" != "0" ]; then
summary "Could not mount the snapshot of $device"
- FINAL_STATUS="ERROR"
+ set_error
if [ "$RETVAL" = "100" ]; then
summary "Could not remove the snapshot !"
- FINAL_STATUS="CRITICAL"
+ set_critical
finish
fi
continue
summary "INCREMENTAL backup of $device done on `NOW`."
elif [ "$RETVAL" = "1" ]; then
summary "Error during incremental backup of $device"
- FINAL_STATUS="ERROR"
+ set_error
elif [ "$RETVAL" = "2" ]; then
summary "Can't do an incremental backup without a full one being present."
summary "Switching to full backup for $device"
summary "FULL backup of $device done on `NOW`."
else
summary "Error during full backup of $device"
- FINAL_STATUS="ERROR"
+ set_error
fi
else
summary "Unknown error during incremental backup of $device"
- FINAL_STATUS="ERROR"
+ set_error
fi
else # Do a full backup
make_full_backup ${BACKUP_SOURCE} $group $volume
summary "FULL backup of $device done on `NOW`."
else
summary "Error during full backup of $device"
- FINAL_STATUS="ERROR"
+ set_error
fi
fi
unmount_snapshot $vg
if [ "$?" != "0" ]; then
summary "Could not unmount snapshot !"
- FINAL_STATUS="CRITICAL"
+ set_critical
finish
fi
remove_snapshot $vg
if [ "$?" != "0" ]; then
summary "Could not destroy the snapshot !"
- FINAL_STATUS="CRITICAL"
+ set_critical
finish
fi
fi
+
done
-finish
+# Push everything on the FTP
+if [ "$USE_FTP" = "yes" ]; then
+ summary ""
+ for group in `grep -v -E '^[[:space:]]*(#.*)?$' $BACKUPTAB | awk '{print $3}' | sort -u`
+ do
+ ftp_push "$REPODIR/$group" $group
+ summary "Mirrored ${group} to ${FTP_HOST}."
+ done
+fi
-## Example Backup description table
-##
-## Can handle logical volumes, with snapshots, or plain mountpoints.
-## Priority is not used yet.
-#
-## Partition or LV Snapshot Host name Volume name Priority
-## ----------------------------------------------------------------------------
-#/ no cottman root 1
-#/dev/vg00/kadarin-root yes kadarin root 1
-#/dev/vg00/valeron-root yes valeron root 1
-#/dev/vg00/syrtis-root yes syrtis root 1
-#/dev/vg00/syrtis-home yes syrtis home 1
-#/dev/vg00/syrtis-usr yes syrtis usr 1
-#/dev/vg00/syrtis-var yes syrtis var 1
-#/dev/vg00/syrtis-srv yes syrtis srv 1
+
+finish