X-Git-Url: https://git.alrj.org/?p=brioche.git;a=blobdiff_plain;f=brioche;h=ca4501d9c167fd688e6faf93da33af68a530f083;hp=2ccf1c3608769a6dc5a1b8a536a3cca7cd36850a;hb=HEAD;hpb=902cf37d03ebaa6f3b7a5ff645a13945f8ee2e57 diff --git a/brioche b/brioche old mode 100644 new mode 100755 index 2ccf1c3..ca4501d --- a/brioche +++ b/brioche @@ -3,20 +3,23 @@ # Brioche Backup # Full and Incremental backup script with tar and LVM snapshots. # -# Copyright Amand Tihon, 2008, 2009 -# Licensed under GNU GPL version 2.0. -# Inspired by -# http://blog.kagesenshi.org/2008/01/automated-tar-and-dump-incremental.html +# Copyright (C) 2008, 2009 Amand Tihon # -# Note: This script relies on GNU tar specific options, -# do not attempt to use it as-is with other tar implementations. +# 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. # +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . # -# 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 +# Note: This script relies on GNU tar specific options, +# do not attempt to use it as-is with other tar implementations. # Mandatory @@ -38,12 +41,10 @@ SNAPSHOT_NAME="backup-snap" 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 @@ -76,6 +77,26 @@ summary() 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 @@ -83,9 +104,7 @@ finish() 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 @@ -230,23 +249,71 @@ make_incr_backup() 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; rm -rf ${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; rm -rf 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 ####################################################################### @@ -260,14 +327,14 @@ then 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 @@ -294,6 +361,10 @@ case "$COMPRESS" in lzma) COMPRESS_OPT="--lzma" ;; + none) + COMPRESS_OPT="" + COMPRESS="" + ;; *) summary "Unknown compression method: ${COMPRESS}. Falling back to gzip." COMPRESS="gz" @@ -305,6 +376,14 @@ esac # 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 @@ -322,7 +401,7 @@ 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 @@ -331,10 +410,10 @@ do 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 @@ -354,7 +433,7 @@ do 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" @@ -363,11 +442,11 @@ do 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 @@ -375,7 +454,7 @@ do summary "FULL backup of $device done on `NOW`." else summary "Error during full backup of $device" - FINAL_STATUS="ERROR" + set_error fi fi @@ -386,35 +465,31 @@ do 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