/ Published in: Bash
                    
                                        
                            
                                Expand |
                                Embed | Plain Text
                            
                        
                        Copy this code and paste it in your HTML
#!/bin/bash
#
# Saibal MySQL Backup Script
#
# VER. 1.1 - http://www.lorenzone.it
# Copyright (c) 2010 [email protected]
#
# BY IDEA OF DAVIDE BUZZI'S SCRIPT. THANK YOU BROTHER!
# THANK YOU TO MR. GLAUCO TOO!
#
# 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 2 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, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#=====================================================================
#=====================================================================
# CHANGELOG
#=====================================================================
# Versione 1.1
# Separazione funzioni dump e compressione
# Aggiunti controlli sulla creazione delle cartelle e dei file
# Sostituzione funzione touch con echo -e per la creazione del file di log
# Sostituzione del comando LET per le operazioni di incremento contatori
# Rivisitazione generale del codice
# Versione 1.0
# Aggiunto invio log per email
# Aggiunto trasferimento FTP
# Controllo generale del codice
#
# Versione 0.5
# Aggiunto backup giornaliero
# Aggiunto backup mensile
# Aggiunta registrazione dei log
#=====================================================================
# TO REMEMBER
#=====================================================================
#
# 1) nelle operazioni per aumentare i contatori potrei usare il comando "let". Es.: 'let CONTA++' aumenta di 1 il contatore
# Si però tratta di un "bashismo" che non mi assicura la compatibilità su altre shell.
# Per questo motivo utilizzo l'espasione classica. Es.: CONTA=$(( CONTA + 1 )).
# 2) Per creare un file potrei usare "touch" ma per avere un corretto return-code ($?) se esiste una dir
# con lo stesso nome uso 'echo -n'. il parametro -n non inserisce una riga vuota nel nuovo file creato
#=====================================================================
# Configurazione generale
#=====================================================================
# host database
DBHOST='localhost'
# username database
USERNAME='root'
# password database
PASSWORD=''
# lista dei database da salvare (separati da spazio)
DATABASES='mysql'
# directory dove salvare i backup (senza slash finale)
OUT_DIR='/home/UTENTE/bk_database'
# formato data (it oppure en)
DATE_FORMAT='it'
# backup mensile? (y oppure n)
MONTHLY_BACKUP='y'
# giorno del mese in cui effettuare il backup mensile (formato 01, 02, 03, etc)
MONTHLY_BKDAY='01'
# cartella backup giornalieri
DAILY_FOLDER='daily'
# cartella backup mensili
MONTHLY_FOLDER='monthly'
# cartella ultimo backup
LAST_FOLDER='last'
#=====================================================================
# Configurazione logs
#=====================================================================
# registrazione dei log? (y oppure n)
LOGS_REC='y'
# directory dove salvare i LOG. Se lasciata vuota sarà la stessa dei backup (senza slash finale)
LOGS_DIR=''
# cartella dei LOG
LOGS_FOLDER='dumplog'
# nome del file di LOG
LOGS_FILENAME='dump.log'
# dimensione massima del file di log (in KB)
LOGS_MAXSIZE='900'
#=====================================================================
# Configurazione invio email
#=====================================================================
# abilitare invio email con risultato delle operazioni? (y oppure n)
EMAIL_SEND='n'
# inviare email solo in caso di errore? (y oppure n)
EMAIL_ONLYERRORS='y'
# programma da utilizzare
EMAIL_SERVICE='sendmail'
# destinatario email
EMAIL_RECIVER='[email protected]'
# soggetto email
EMAIL_SUBJECT='MySQL Backup - resoconto'
#=====================================================================
# Configurazione ftp
#=====================================================================
# abilitare trasferimento FTP dei backup? (y oppure n)
FTP_TRANSF='n'
# trasferire backup giornalieri o solo i last? (d oppure l)
FTP_FILES='d'
# indirizzo FTP
FTP_HOST='123.123.123.123'
# username FTP
FTP_USER='xx'
# password FTP
FTP_PASSWORD='xx'
# directory in cui inserire i file
FTP_REMOTEDIR='/public_html/bk_db'
# file temp. per il log dei comandi di console FTP. Il risultato dell'operazione viene invece registrato sul file generale
FTP_LOGS_FILENAME='ftp.log'
#=====================================================================
# Configurazione messaggi
#=====================================================================
# messaggi di ritorno per il backup (NOMEDB è un placeholder. se possibile non cancellare)
BACKUP_OK="BACKUP RIUSCITO! | $HOSTNAME | Tutti i backup effettuati con successo"
BACKUP_KO="ERRORE BACKUP! | $HOSTNAME | I seguenti database: NOMEDB non sono stati copiati e/o compressi"
CONNEC_KO="ERRORE MYSQL! | $HOSTNAME | Impossibile connettersi ai seguenti database: NOMEDB"
SEMAIL_KO="ERRORE INVIO! | $HOSTNAME | Impossibile trovare il servizio $EMAIL_SERVICE per inviare messaggi"
FTPPUT_OK="FTP RIUSCITO! | $HOSTNAME | Tutti i file sono stati trasferiti con successo sul server $FTP_HOST"
FTPPUT_KO="ERRORE FTP! | $HOSTNAME | Errore procedura FTP. Errore: FTPERR"
########################################
# START CODE - BE CAREFUL WHEN EDITING
########################################
#=========================================
# FUNZIONI VARIE
#=========================================
# funzione per controllare la corretta creazione delle directory e dei file
check_build() {
# $1 è il return code dell'operazione precedente ($?) | $2 è il nome della dir che si è tentato di creare
if [ "$1" -eq "1" ]
then
echo "Errore nel creare $2. Controllare che non esista un file/directory con lo stesso nome"
exit
fi
}
# funzione per check invio email
check_email() {
if [ "$EMAIL_SEND" = "y" ]
then
CHECK_MAIL=$(which $EMAIL_SERVICE)
if [ -n "$CHECK_MAIL" ]
then
MAIL_RESULT=1
else
MAIL_RESULT=0
# aumento il contatore
ERROR_NOMAIL_SERVICE=$(( ERROR_NOMAIL_SERVICE + 1 ))
fi
else
MAIL_RESULT=0
fi
return $MAIL_RESULT
}
# funzione per check connessione al database
check_connection() {
# testo la connessione
mysql --user=$USERNAME --password=$PASSWORD $DB -e STATUS > /dev/null 2>&1
# id errore
CONN_ERROR=$?
return $CONN_ERROR
}
# funzione per effettuare il dump al db
do_mysqldump() {
# dump del database
mysqldump --user=$USERNAME --password=$PASSWORD --host=$DBHOST $DB > "$1"
# registro il risultato dell'operazione mysqldump.
DUMP_ERROR=$?
return $DUMP_ERROR
}
# funzione per effettuare la compressione del database
do_compression() {
# comprimo il tutto con gzip
gzip -f "$1"
#risultato operazione gzip
GZIP_ERROR=$?
return $GZIP_ERROR
}
#=========================================
# VARIABILI
#=========================================
# path principali del sistema
PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/mysql/bin:/usr/sbin
# data di oggi
TODAY_DATE=`date +%d/%m/%Y`
# ora di oggi
TODAY_TIME=`date +%T`
# giorno della settimana (1 Lunedì, 2 Martedì, etc etc)
NDAY=`date +%u`
# giorno del mese (formato 01, 02, 03, etc)
DMON=`date +%d`
# mese
MON=`date +%m`
# mese - anno
MONYEA=`date +%m_%Y`
# date esecuzione backup nei due formati
DATEIT=`date +\[%d-%m-%Y_%H-%M\]`
DATEEN=`date +\[%Y-%m-%d_%H-%M\]`
# formato data per i log
LOGDATE="`date +%Y/%m/%d` - `date +%T`"
# dichiaro questa variabile perchè il backup mensile è opzionale
LOGS_RESULT_MONTHLY=0
# contatori di errori
ERROR_CONN_TODB=0
ERROR_COUNT_DAILY=0
ERROR_COUNT_MONTHLY=0
ERROR_NOMAIL_SERVICE=0
ERROR_FTP_TRANSFER=0
# codice per convertire in LOWERCASE le variabili inserite in questo array
TO_LOWER=("DATE_FORMAT" "MONTHLY_BACKUP" "LOGS_REC" "EMAIL_SEND" "EMAIL_ONLYERRORS" "FTP_TRANSF" "FTP_FILES")
for INPUT in "${TO_LOWER[@]}"
do
eval $INPUT="$(echo ${!INPUT} | tr 'A-Z' 'a-z')"
done
# scelgo la formattazione della data
if [ "$DATE_FORMAT" = "it" ]
then
DATE="$DATEIT"
else
DATE="$DATEEN"
fi
# se non esiste la directory OUTDIR la creo
if [ ! -d "$OUT_DIR" ]
then
mkdir -p "$OUT_DIR"
fi
# controllo la creazione della dir
check_build "$?" "$OUT_DIR"
# se non esiste la directory DAILY la creo
if [ ! -d "$OUT_DIR/$DAILY_FOLDER" ]
then
mkdir -p "$OUT_DIR/$DAILY_FOLDER"
fi
# controllo la creazione della dir
check_build "$?" "$OUT_DIR/$DAILY_FOLDER"
# se non esiste la directory LAST la creo
if [ ! -d "$OUT_DIR/$LAST_FOLDER" ]
then
mkdir -p "$OUT_DIR/$LAST_FOLDER"
fi
# controllo la creazione della dir
check_build "$?" "$OUT_DIR/$LAST_FOLDER"
# se non esiste la directory MONTHLY la creo
if [ "$MONTHLY_BACKUP" = "y" ]
then
if [ ! -d "$OUT_DIR/$MONTHLY_FOLDER" ]
then
mkdir -p "$OUT_DIR/$MONTHLY_FOLDER"
fi
# controllo la creazione della dir
check_build "$?" "$OUT_DIR/$MONTHLY_FOLDER"
fi
# se sono abilitati i logs e non esiste la directory LOGS la creo e calcolo la dimensione massima del file
if [ "$LOGS_REC" = "y" ]
then
# se la variabile LOGS_DIR non è vuota la imposto altrimenti inserisco la cartella dentro la directory di default
if [ -n "$LOGS_DIR" ]
then
LOGS_DIR="$LOGS_DIR/$LOGS_FOLDER"
else
LOGS_DIR="$OUT_DIR/$LOGS_FOLDER"
fi
# creo la directory
if [ ! -d "$LOGS_DIR" ]
then
mkdir -p "$LOGS_DIR"
fi
# controllo la creazione della dir
check_build "$?" "$LOGS_DIR"
# creo il file di log
if [ ! -f "$LOGS_DIR/$LOGS_FILENAME" ]
then
echo -ne > "$LOGS_DIR/$LOGS_FILENAME"
fi
# controllo la creazione del file
check_build "$?" "$LOGS_DIR/$LOGS_FILENAME"
# cancello il file log FTP se viene disabilitata la funzione (ma la funzione log generale deve cmq essere attiva!)
if [ "$FTP_TRANSF" != "y" ]
then
rm -f "$LOGS_DIR/$FTP_LOGS_FILENAME"
fi
# converto i KB in BYTES dopo aver controllato che la VAR non sia vuota
if [ -n "$LOGS_MAXSIZE" ]
then
LOGS_MAXBYTES=$(( $LOGS_MAXSIZE*1000 ))
else
LOGS_MAXBYTES=$(( 1000*1000 ))
fi
fi
#=========================================
# START BACKUP NOW!!!
#=========================================
# Controllo l'invio delle email. ritorna $MAIL_RESULT
check_email
# inizio il ciclo sui database
for DB in $DATABASES
do
# funzione per testare la connessione al database. ritorna $CONN_ERROR
check_connection
if [ "$CONN_ERROR" -eq "0" ]
then
########################################
# BACKUP GIORNALIERO
########################################
# rimuovo i vecchi backup (qualsiasi estensione)
rm -f "$OUT_DIR/$DAILY_FOLDER/[${NDAY}]__${DB}__"*
# creo il nome del file da dumpare e comprimere in .gz
OUTFILE="$OUT_DIR/$DAILY_FOLDER/[${NDAY}]__${DB}__${DATE}.sql"
# ci sbatto dentro il dump. ritorna $DUMP_ERROR
do_mysqldump "$OUTFILE"
# comprimo il file. ritorna $GZIP_ERROR
do_compression "$OUTFILE"
# se la compressione è avvenuta rimuovo i vecchi file ".last" e copio l'ultimo gzip creato dentro la dir LAST
if [ "$GZIP_ERROR" -eq "0" ]
then
rm -f "$OUT_DIR/$LAST_FOLDER/${DB}__"*"__last.sql.gz"
# uso la funzione cp
cp "$OUTFILE.gz" "$OUT_DIR/$LAST_FOLDER/${DB}__${DATE}__last.sql.gz"
fi
# uso le VAR di ritorno delle funzioni per gestire gli errori nei log se abilitati
if [ "$LOGS_REC" = "y" ]
then
if [ "$DUMP_ERROR" -gt "0" -o "$GZIP_ERROR" -gt "0" ]
then
# aumento il contatore
ERROR_COUNT_DAILY=$(( ERROR_COUNT_DAILY + 1 ))
# registro i DB nella stessa variabile
ERROR_DB+="[${DB}__giornaliero] "
fi
fi
########################################
# BACKUP MENSILE
########################################
if [ "$MONTHLY_BACKUP" = "y" ]
then
if [ "$DMON" = "$MONTHLY_BKDAY" ]
then
# rimuovo i vecchi backup
rm -f "$OUT_DIR/$MONTHLY_FOLDER/[${MON}_"*"]__${DB}"*
# creo il nome del file da dumpare e comprimere in .gz
OUTFILE="$OUT_DIR/$MONTHLY_FOLDER/[${MONYEA}]__${DB}.sql"
# ci sbatto dentro il dump. ritorna $DUMP_ERROR
do_mysqldump "$OUTFILE"
# comprimo il file. ritorna $GZIP_ERROR
do_compression "$OUTFILE"
# preparo i messaggi di log se abilitati
if [ "$LOGS_REC" = "y" ]
then
if [ "$DUMP_ERROR" -gt "0" -o "$GZIP_ERROR" -gt "0" ]
then
# aumento il contatore
ERROR_COUNT_MONTHLY=$(( ERROR_COUNT_MONTHLY + 1 ))
# registro i DB nella stessa variabile
ERROR_DB+="[${DB}__mensile] "
fi
fi
fi
fi
else
if [ "$LOGS_REC" = "y" -o "$MAIL_RESULT" -eq "1" ]
then
# aumento il contatore
ERROR_CONN_TODB=$(( ERROR_CONN_TODB + 1 ))
# registro i DB nella stessa variabile
ERROR_CONN_DB+="[${DB}] "
fi
fi
done
#=========================================
# FTP SECTION!!!
#=========================================
if [ "$FTP_TRANSF" = "y" -a "$CONN_ERROR" -eq "0" ]
then
if [ "$FTP_FILES" = "d" ]
then
FTP_FOLDER="$DAILY_FOLDER"
MFILENAME="*[${NDAY}]*]*.gz"
else
FTP_FOLDER="$LAST_FOLDER"
MFILENAME="*__last*.gz"
fi
echo "
open $FTP_HOST
user $FTP_USER $FTP_PASSWORD
binary
lcd $OUT_DIR/$FTP_FOLDER
cd $FTP_REMOTEDIR
mdelete $MFILENAME
mput $MFILENAME
close
quit" | ftp -in -v > "$LOGS_DIR/$FTP_LOGS_FILENAME" 2>&1
# visto che le funzioni FTP fanno schifo cerco in qualche maniera di intercettare gli errori
# non connesso
FTP_TRAPERR=`grep -i "Not connected." "$LOGS_DIR/$FTP_LOGS_FILENAME"`
if [ "$?" -eq "0" ]
then
# aumento il contatore
ERROR_FTP_TRANSFER=$(( ERROR_FTP_TRANSFER + 1 ))
ERROR_FTP_RESULT="${ERROR_FTP_RESULT}Connessione al server FTP fallita | "
fi
# autenticazione fallita
FTP_TRAPERR=`grep -i "Login authentication failed" "$LOGS_DIR/$FTP_LOGS_FILENAME"`
if [ "$?" -eq "0" ]
then
# aumento il contatore
ERROR_FTP_TRANSFER=$(( ERROR_FTP_TRANSFER + 1 ))
ERROR_FTP_RESULT="${ERROR_FTP_RESULT}Autenticazione fallita | "
fi
# directory remota non trovata
FTP_TRAPERR=`grep -i "change directory to $FTP_REMOTEDIR" "$LOGS_DIR/$FTP_LOGS_FILENAME"`
if [ "$?" -eq "0" ]
then
# aumento il contatore
ERROR_FTP_TRANSFER=$(( ERROR_FTP_TRANSFER + 1 ))
ERROR_FTP_RESULT="${ERROR_FTP_RESULT}Directory remota non trovata | "
fi
# non trovo i file
FTP_TRAPERR=`grep -i "no such" "$LOGS_DIR/$FTP_LOGS_FILENAME"`
if [ "$?" -eq "0" ]
then
# aumento il contatore
ERROR_FTP_TRANSFER=$(( ERROR_FTP_TRANSFER + 1 ))
ERROR_FTP_RESULT="${ERROR_FTP_RESULT}File o directory non trovati | "
fi
# app chiusa
FTP_TRAPERR=`grep -i "killed" "$LOGS_DIR/$FTP_LOGS_FILENAME"`
if [ "$?" -eq "0" ]
then
# aumento il contatore
ERROR_FTP_TRANSFER=$(( ERROR_FTP_TRANSFER + 1 ))
ERROR_FTP_RESULT="${ERROR_FTP_RESULT}Processo di trasferimento abbandonato | "
fi
# spazio su disco esaurito (come me!! bwuahbwuah)
FTP_TRAPERR=`grep -i "space" "$LOGS_DIR/$FTP_LOGS_FILENAME"`
if [ "$?" -eq "0" ]
then
# aumento il contatore
ERROR_FTP_TRANSFER=$(( ERROR_FTP_TRANSFER + 1 ))
ERROR_FTP_RESULT="${ERROR_FTP_RESULT}Mancanza di spazio su disco"
fi
fi
#=========================================
# MAIL SECTION!!!
#=========================================
if [ "$MAIL_RESULT" -eq "1" ]
then
# se viene scelto di ricevere una email anche quando le operazioni sono OK
if [ "$EMAIL_ONLYERRORS" = "n" ]
then
# se tutti i dump sono OK invio il messaggio relativo
if [ "$ERROR_CONN_TODB" -eq "0" -a "$ERROR_COUNT_DAILY" -eq "0" -a "$ERROR_COUNT_MONTHLY" -eq "0" ]
then
BACKUP_OK="$LOGDATE | $BACKUP_OK"
# se è attivo il trasferimento file e non ci sono errori aggiungo una parte di messaggio
if [ "$FTP_TRANSF" = "y" -a "$ERROR_FTP_TRANSFER" -eq "0" ]
then
BACKUP_OK="$BACKUP_OK | $FTPPUT_OK"
fi
echo "$BACKUP_OK" | mail -s "$EMAIL_SUBJECT" $EMAIL_RECIVER
fi
fi
# invio email errore backup giornaliero o mensile
if [ "$ERROR_COUNT_DAILY" -gt "0" -o "$ERROR_COUNT_MONTHLY" -gt "0" ]
then
BACKUP_KO="$LOGDATE | $BACKUP_KO"
BACKUP_KO=${BACKUP_KO//NOMEDB/$ERROR_DB}
echo "$CONNEC_KO" | mail -s "$EMAIL_SUBJECT" $EMAIL_RECIVER
fi
# invio email errore connessioni al database
if [ "$ERROR_CONN_TODB" -gt "0" ]
then
CONNEC_KO="$LOGDATE | $CONNEC_KO"
CONNEC_KO=${CONNEC_KO//NOMEDB/$ERROR_CONN_DB}
echo "$CONNEC_KO" | mail -s "$EMAIL_SUBJECT" $EMAIL_RECIVER
fi
# invio email errore trasferimento file
if [ "$ERROR_FTP_TRANSFER" -gt "0" ]
then
FTPPUT_KO="$LOGDATE | $FTPPUT_KO"
FTPPUT_KO=${FTPPUT_KO//FTPERR/$ERROR_FTP_RESULT}
echo "$FTPPUT_KO" | mail -s "$EMAIL_SUBJECT" $EMAIL_RECIVER
fi
fi
#=========================================
# LOGS SECTION!!!
#=========================================
if [ "$LOGS_REC" = "y" ]
then
echo ======================================================================
echo Saibal MySQL Backup
echo
echo Start time: $TODAY_TIME - $TODAY_DATE
echo Backup of MySQL Databases \(powered by saibal - saibal@lorenzone.it\)
echo ======================================================================
echo Risultato delle operazioni:
echo
# dimensione del file per vedere quando troncarlo
LOG_SIZE=$( stat -c %s "$LOGS_DIR/$LOGS_FILENAME")
# se la misura attuale è più grande di quella massima tronco il file e ricomincio
if [ $LOG_SIZE -gt "$LOGS_MAXBYTES" ]
then
# con il parametro -n non metto una riga vuota nel file
echo -ne > "$LOGS_DIR/$LOGS_FILENAME"
fi
# se vengono rilevati errori nel servizio di posta
if [ "$ERROR_NOMAIL_SERVICE" -gt "0" ]
then
SEMAIL_KO="$LOGDATE | $SEMAIL_KO"
echo "$SEMAIL_KO"
echo "$SEMAIL_KO" >> "$LOGS_DIR/$LOGS_FILENAME"
fi
# se c'è un problema FTP stampo il messaggio
if [ "$ERROR_FTP_TRANSFER" -gt "0" ]
then
FTPPUT_KO="$LOGDATE | $FTPPUT_KO"
FTPPUT_KO=${FTPPUT_KO//FTPERR/$ERROR_FTP_RESULT}
echo "$FTPPUT_KO"
echo "$FTPPUT_KO" >> "$LOGS_DIR/$LOGS_FILENAME"
elif [ "$FTP_TRANSF" = "y" -a "$ERROR_FTP_TRANSFER" -eq "0" ]
then
FTPPUT_OK="$LOGDATE | $FTPPUT_OK"
echo "$FTPPUT_OK"
echo "$FTPPUT_OK" >> "$LOGS_DIR/$LOGS_FILENAME"
fi
# se tutti i dump sono OK stampo il messaggio relativo
if [ "$ERROR_CONN_TODB" -eq "0" -a "$ERROR_COUNT_DAILY" -eq "0" -a "$ERROR_COUNT_MONTHLY" -eq "0" ]
then
# replace di alcune variabili
BACKUP_OK="$LOGDATE | $BACKUP_OK"
echo "$BACKUP_OK"
echo "$BACKUP_OK" >> "$LOGS_DIR/$LOGS_FILENAME"
# se i dump (mensile e/o giornaliero) fallisce stampo un determinato messaggio
else
if [ "$ERROR_COUNT_DAILY" -gt "0" -o "$ERROR_COUNT_MONTHLY" -gt "0" ]
then
BACKUP_KO="$LOGDATE | $BACKUP_KO"
BACKUP_KO=${BACKUP_KO//NOMEDB/$ERROR_DB}
echo "$BACKUP_KO"
echo "$BACKUP_KO" >> "$LOGS_DIR/$LOGS_FILENAME"
fi
# se c'è un problema di connessione al database stampo il messaggio
if [ "$ERROR_CONN_TODB" -gt "0" ]
then
CONNEC_KO="$LOGDATE | $CONNEC_KO"
CONNEC_KO=${CONNEC_KO//NOMEDB/$ERROR_CONN_DB}
echo "$CONNEC_KO"
echo "$CONNEC_KO" >> "$LOGS_DIR/$LOGS_FILENAME"
fi
fi
fi
exit
URL: http://www.lorenzone.it/my-ubuntu/script-bash-per-il-backup-dei-database-mysql/764/
Comments
 Subscribe to comments
                    Subscribe to comments
                
                