PrettyPrint JavaScript

giovedì 1 novembre 2012

Gestione del Backup

In questo post vedremo come organizzare il backup in una macchina Linux. Lo scenario è quello in cui si hanno diverse directory sparse per il file system, delle quali si vuole una copia. Inoltre sulla macchina è installato il plugin di dropbox e viene richiesto di gestire la copia di alcune directory all'interno di quella appartenente a Dropbox e di gestire automaticamente il demone dropboxd per l'upload nella cloud di tali directory.

Il modo più banale per eseguire questo task è il seguente:

Preparo uno script che sincronizza le cartelle di origine e di destinazione. Utilizzo a questo scopo il comando rsync che permette il backup incrementale ottimizzando così i tempi di copia.

synch.sh:

#!/bin/bash
rsync -avrz --delete --force --copy-dirlinks --omit-dir-times /another/path/to/Ebook/  "/backup/Ebook/"
rsync -avrz --delete --force --copy-dirlinks --omit-dir-times /path/to/Musica/  "/backup/Musica/"
rsync -avrz --delete --force --copy-dirlinks --omit-dir-times /path/to/my/Documenti/  "/backup/Documenti/" 
rsync -avrz --delete --force --copy-dirlinks --omit-dir-times /path/to/my/Documenti/  "/Dropbox/Documenti/" 



Dopodichè configuro crontab* per esegure lo script e per lanciare e terminare dropbox:
./dropbox-dist/dropboxd
 killall -9 dropbox
 
* Maggiori informazioni sull'utilizzo di crontab: http://www.manpagez.com/man/5/crontab/ 

Tuttavia questa soluzione risulta scomoda nel momento in cui dobbiamo aggiungere directory al backup o in cui cambiano i percorsi delle nostre directory.

Un metodo che garantisce maggiore flessibilità è quello di creare due directory che chiameremo: toSynch e toDropbox, all'interno delle quali creeremo dei link simbolici verso le directory di cui vogliamo una copia nella directory di backup o in quella Dropbox:



 Lo script in questo modo viene notevolmente semplificato e diventa:

#!/bin/bash
rsync -avrz --delete --force --copy-dirlinks --omit-dir-times /path/toBackup/  "/backup/"
rsync -avrz --delete --force --copy-dirlinks --omit-dir-times /path/toDropbox/  "/Dropbox/"


In questo modo se vogliamo aggiungere delle nuove directory al backup o a Dropbox, o semplicemente cambiano i percorsi delle directory basterà rispettivamente aggiungere o modificare i link simbolici all'interno delle directory toBackup e toDropbox.

A questo punto sarebbe asupicabile aggiungere al nostro sistema di backup la generazione di un log delle operazioni e la gestione degli eventuali errori e relativa notifica.

Per fare ciò avremo tre diversi livelli di log:
  • /var/log/backup.log: log delle operazioni dello script;
  • /var/log/backup_err.log: log degli errori;
  • /var/tmp/backup.tmp: log temporaneo con gli output dei singoli comandi lanciati;
Gli obiettivi sono quelli di verificare che l'operazione di backup sia andata a buon fine, ricevere una notifica (preferibilmente una mail) in caso di errori, avere tutte le informazioni necessarie a risolvere gli eventuali errori.

Per raggiungere questo obiettivo avremo bisogno di uno script in grado di interpretare alcuni comandi in particolare i seguenti:

- esegui la copia di backup;
- start dropbox
- stop drobox
- controllo degli errori ed invio mail*

Il seguente script utilizza dropbox.py per lo start e lo stop di Dropbox scaricabile direttamente da: http://www.dropbox.com/download?dl=packages/dropbox.py

Inoltre si utilizza postfix per l'invio di mail tramite riga di comando: http://www.postfix.org/BASIC_CONFIGURATION_README.html

Lo script utilizza inoltre un file di configurazione nel quale vengono specificati:
  • Il path dei file di log
  • Il path delle directory di origine e destinazione del backup
  • Le informazioni relative alla mail da inviare in caso di errori 


smartbackup.sh:
#!/bin/bash
#This script synch the directory listed into 'synchList' as [FROM] [TO] string
#It also provide to start or stop dropbox based on a command line option. 
#It write the standard output to a crontab.log file into /var/log directory and a standard error into
#crontab_error.log file in the same directory. If an error occours and crontab_error.log is not empty
#send a mail to 'mailTo' address from a 'sendTo' address based on mail account configured on system.
#Required dropbox.py on dropbox home path. dropbox.py are available on: http://www.dropboxwiki.com/Using_Dropbox_CLI

############################################## VARIABLES ##############################################
set -e
trap trapcatcher INT TERM EXIT 

PROGNAME=$(basename $0)
USAGESTR="Usage: $PROGNAME [-s] [-d] [OPTION] [-v]"

source /etc/smartbackup.conf

START="start"
STOP="stop"
DEBUG=0
MAIL=0
SYNCHRONIZE=0
DROPBOXSTART=0
DROPBOXSTOP=0

function trapcatcher
{
#   ----------------------------------------------------------------
#   Function managing fatal program error or unhandled signal
#   ----------------------------------------------------------------
    echo $name $(date) " GRAVE: Some unhandled errors occours. " >> $log
    echo "${PROGNAME} (ERROR): ${1:-"Unknown Error"}" 1>&2
    exit 1;
}

function error_exit
{

#   ----------------------------------------------------------------
#   Function for exit due to handled program error
#       Accepts 1 argument:
#           string containing descriptive error message
#   ----------------------------------------------------------------

        
    echo "${PROGNAME} (ERROR): ${1:-"Unknown Error"}" 1>&2
    exit 0
}

function USAGE ()
{

#   ----------------------------------------------------------------
#   Function for explain the proper command usage
#   ----------------------------------------------------------------


    echo ""
    echo $USAGESTR
    echo ""
    echo "OPTIONS:"
    echo "    -s  start synchronize"
    echo "    -d  [OPTION] start or stop dropbox option can be start or stop"
    echo "    -v  print version"
    echo "    -m  send mail if errors occours"
    echo "    -D  debug mode on"    
    echo "    -h  print this help"
    echo ""
    echo "EXAMPLE:"
    echo "    `basename $0` -s -d start -v -m"
    echo ""
    #exit $E_OPTERROR    # Exit and explain usage, if no argument(s) given.
}

function synchronize() {

#   ----------------------------------------------------------------
#   Function for exec the rsynch command to dir list
#   ----------------------------------------------------------------
    
    notify-send Backup "Start Synchronizing Script"
    echo $name $(date) " Start synch procedure..." >> $log

    #Cicla gli array ed esegue un rsync per ognuno di essi
    for syncStr in ${syncList[@]}
    do
        #IFS=$IFS_OLD    #Restore old separator    
        arr=$(echo $syncStr | tr ";" "  ")
        echo $name $(date) " Synchronized (from to) ${arr[0]} ${arr[1]}" >> $log
    rsync -avrz --delete --force --copy-dirlinks --omit-dir-times ${arr[0]}  ${arr[1]} >>$tempFile 2>> $errorLog        
        
    done
    
    # --------------------------------------------------------------------
    # Insert here other operation to do for synchronize
    # --------------------------------------------------------------------
   

    echo $name $(date) " Synch procedure succesfully end" >> $log
    notify-send Backup "End Synchronizing"
}

function manageDropbox() {

    if [ $DROPBOXSTART -eq 1 ];
    then
        echo $name $(date) " Run Dropbox..." >> $log
        exec $DROPBOX_HOME./dropboxd & 2>> $errorLog
    elif [ $DROPBOXSTOP -eq 1  ];
    then
        python2.7 $DROPBOX_PY_PATH stop 2>> $errorLog
        echo $name $(date) " Stopped dropbox" >> $log
    fi
    
}

function sendMail() {
    #Se sono presenti degli errori esiste e non è vuoto 
    # il file crontab_error che quindi invio per mail
    if [ -s $errorLog ];
    then
           echo $name $(date) " Some errors occours. See crontab_error.log. An email was send. " >> $log
           #Send email        
           echo "$mailBody" | mail -s "$mailSubject" -a "$errorLog" -r "$mailTo" "$mailFrom" 2>> $errorLog
        
    else
        #deleting temp file
        echo $name $(date) " Deleting temp file: $tempFile" >> $log
        rm $tempFile 2>>$errorLog        
           echo $name $(date) " Backup successfully end. " >> $log
        
    fi

}

#   ----------------------------------------------------------------
#   Start Script 
#   ----------------------------------------------------------------

# Parse command line options.
while getopts svDhmd: OPT; do
    case "$OPT" in
        s)
            SYNCHRONIZE=1
            ;;
        d)
            manageDropbox $OPTARG
        if [ $OPTARG = $START ];
        then
            DROPBOXSTART=1
        elif [ $OPTARG = $STOP ];
        then
            DROPBOXSTOP=1
        else 
        echo USAGE 1>&2
        error_exit "$LINENO: Invalid -d Option: only start and stop permitted"
        fi
            ;;
    m)
            MAIL=1
            ;;
    D)
        DEBUG=1
            #logError="/dev/stderr" #Dangerous
        #log="/dev/stdout"    #Dangerous
            ;;
    v)
            echo "$name v.$version"    
            ;;
    h)
        USAGE
            ;;
        \?)
            # getopts issues an error message
            USAGE 1>&2
        error_exit "$LINENO: Invalid Option "
            ;;
    esac
done

# Remove the switches we parsed above.
# shift `expr $OPTIND - 1`

# We want at least one non-option argument. 
# Remove this block if you don't need it.
if [ $# -eq 0 ]; then
    USAGE 1>&2
    error_exit "$LINENO: At least one non-option argument is needed "
fi

#   ----------------------------------------------------------------
#   Based on the current active flag execute the proper command in the
#   right order
#   ----------------------------------------------------------------

if [ $SYNCHRONIZE -eq 1 ];
then synchronize
fi

if [[ $DROPBOXSTART -eq 1 || $DROPBOXSTOP -eq 1 ]];
then 
    manageDropbox
fi

if [ $MAIL -eq 1 ];
then
    sendMail
fi


#Reset trap setting
trap - INT TERM EXIT



smartbackup.conf:
#Configuration file for smartbackup.sh

#Name and version script
name="smartbackup"
version="1.4"
#Notify mail to
mailTo="mail@yourAccount.com" 
#Notify mail from
mailFrom="mail@yourAccount.com"
#Subject
mailSubject="BACKUP ERROR NOTIFY"
#Body
mailBody="This mail contains the system backup error log. Remember to clean crontab_error.log"

#Temp file
tempFile="/var/tmp/smartbackup.tmp"
#Error log path
errorLog="/var/log/crontab_error.log"
#Common logging file for this backup
log='/var/log/crontab.log'
#Dropbox home path
DROPBOX_HOME="/home/yournickname/programs/dropbox/"
#dropbox.py home path
DROPBOX_PY_PATH="/home/yournickname/dropbox.py"

#TO SYNCHRONIZE
syncList[0]="/path/toBackup/;/media/yourMedia/backup/"
syncList[1]="/path/toSynch/;/media/Dropbox/"




Nessun commento:

Posta un commento