#!/bin/sh # Realiza un respaldo de las bases de datos
# y los archivos de las paginas web ya sea en local o remoto
# Para backup remoto se asumira que localhost es el origen de los datos
#
#
# Variables de rutas, ubicacion de las bases de datos, paginas
# y comandos necesarios para la ejecucion
# Nombre o direccion IP del host remoto, en blanco si el backup se hara en local
HOST_REMOTO=servbackup.dominio.com
# Nombre de usuario remoto, en blanco si el backup se ará en local
USUARIO_REMOTO=rbackup
# Puerto remoto a la escucha de ssh
PUERTO_REMOTO=222
# Nombre de los directorios que contienen las paginas web
# Cada directoro se actualizará mediante una nueva conexion rsync
PAGINAS="/var/www/pagina1 /var/www/pagina2 /var/www/paginax"
# Bases de datos de las que se realizara el backup
# Si se omite se ejecutará mysqldump con la opcion --all-databases
MYSQL_DATABASES="una_base_de_datos otra_base_de_datos y_otra_mas"
# Otros archivos a sincronizar
OTROS="/etc/apache2 /var/log/rbackup"
# Directorio temporal al cual se realizara el dump de la base de datos para luego ser transferida
TMP=/tmp
# Directorio donde se almacenaran los registros de log (en local)
DIR_LOG=/var/log/rbackup
# Nombre del archivo de log
ARCH_LOG=rbackup.log
# Nombre del archivo de debug, el archivo solo se conservará si
# Se lo indica en la variable CONSERVAR_DEBUG o si ocurrieran errores
ARCH_DEBUG=`date +rbackup-%d-%m-%Y-%H:%M.debug`
# Coservar el archivo de debug, cero por NO, cualquier otro valor por SI
CONSERVAR_DEBUG=1
# Directorio destino del backup
RUTA_DESTINO=/var/rbackup
# Nombre de usuario valido y con suficientes privilegios para realizar dump de las bases de datos.
# Puede omitirse si no se requiere de ninguno
MYSQL_USER=usuario
# Password del usuario, puede omitirse
MYSQL_PASSWORD=clave
# Otras opciones a agregar al guión de ejecucion de mysqldump
# --verbose y --force son buena idea
# --default-character-set=latin1 es recomendable para
# base de datos mysql 4.0 o anteriores
OPCIONES_MYSQLDUMP='--default-character-set=latin1 --verbose --force'
################################################################################################################
# Agrega un registro al archivo de log
# Si se especifica la opcion -p tambien lo muestra por pantalla
log(){
echo `date "+%d %b %r"`" "$1 >> $ARCH_LOG
test +$2 == '+-p' && echo `date "+%d %b %r"`" "$1
}
# Coloca ruta absoluta a los archivos de log
ARCH_LOG=${DIR_LOG}/$ARCH_LOG
ARCH_DEBUG=${DIR_LOG}/$ARCH_DEBUG
# Comprueba que existe el directorio de log y el archivo de log, lo crea si no existiera
# El script termina con error si no se pudiera lograr esto con exito
! test -d $DIR_LOG && mkdir --parent $DIR_LOG
! test -d $DIR_LOG && echo "Error fatal: El directorio de destino de los archivos de log y debug no existe y no puede crearse" && exit 1
! test -e $ARCH_LOG && echo "Creando archivo de log" && touch $ARCH_LOG
! test -w $ARCH_LOG && echo "Error fatal: El archivo de log $ARCH_LOG no existe y no puede crearse y/o modificarse" && exit 1
! test -e $ARCH_DEBUG && touch $ARCH_DEBUG
! test -w $ARCH_DEBUG && log "Error fatal: El archivo de debug $ARCH_DEBUG no pudo crearse y/o modificarse" -p && exit 1
log 'Iniciando backup'
logger -t $0 'Iniciando backup'
echo -- DEBUG FILE -- [ `date "+%d %b %r"` ] >> $ARCH_DEBUG
# Da el formato adecuado a las variables referentes a las bases de datos
# Le asigna a la variable MYSQL_USER el formato --user=nombre pero deja la cadena vacia si no se ha especificado usuario.
test -z $MYSQL_USER || MYSQL_USER="--user=$MYSQL_USER"
# Le asigna a la variable MYSQL_PASSWORD el formato "--password=password" pero deja la cadena vacia si no se ha especificado password.
test -z $MYSQL_PASSWORD || MYSQL_PASSWORD="--password=$MYSQL_PASSWORD"
# Si se han especificado bases de datos se le da el formato "--databases lista de las bases de datos"
# Se le asigna el valor "-all-databases" en caso contrario
test -z "$MYSQL_DATABASES" || MYSQL_DATABASES="--databases $MYSQL_DATABASES"
test -z "$MYSQL_DATABASES" && MYSQL_DATABASES="--all-databases"
# Da el formato adecuado al destino segun sea local o remoto
! test -z $USUARIO_REMOTO && ! test -z $HOST_REMOTO && RUTA_DESTINO=${USUARIO_REMOTO}@${HOST_REMOTO}:${RUTA_DESTINO}
# Realiza el respaldo de la base de datos en local $TMP
log "Creando archivo de dump de las bases de datos en \"${TMP}/databases.sql\""
mysqldump $OPCIONES_MYSQLDUMP $MYSQL_USER $MYSQL_PASSWORD $MYSQL_DATABASES --result-file ${TMP}/databases.sql 2> $ARCH_DEBUG
# Si el proceso mysqldump no finalizo correctamente se registra una alerta en el archivo de log y se conserva
# el archivo debug, de lo contrario el archivo debug es eliminado y la base de datos se transfiere al host remoto
ERROR=$?
if [ $ERROR -ne 0 ];
then
log "ATENCION: El proceso mysqldump ha finalizado con código de salida $ERROR, para evitar reemplazar el archivo de backup de la base de datos anterior por un archivo corrupto se ha omitido la sincronizacion. Vea el archivo $ARCH_DEBUG para obtener información detallada del error."
else
log "Inicio del backup de la base de datos; destino: \"${RUTA_DESTINO}/database/databases.sql\""
echo `date "+%d %b %r"`" -- MARK --" >> $ARCH_DEBUG
rsync -e "ssh -p $PUERTO_REMOTO" -avz ${TMP}/databases.sql $RUTA_DESTINO/database/ 2>&1 >> $ARCH_DEBUG
ERROR=$?
if [ $ERROR -ne 0 ];
then
log "ATENCION: La transferencia del archivo de dump de la base de datos ha finalizado con código de salida $ERROR. Vea el archivo $ARCH_DEBUG para obtener información detallada del error."
test +$CONSERVAR_DEBUG == '+0' && rm $ARCH_DEBUG
fi
fi
log "Inicio del backup de archivos, destino: \"${RUTA_DESTINO}/paginas/\""
# Realiza el respaldo de los archivos de paginas
# Si ocurre algun error se loguea
for ARCHIVOS in $PAGINAS
do
log "Actualizando \"${ARCHIVOS}\" en \"${RUTA_DESTINO}/paginas/\""
RS_OUTPUT=`rsync -e "ssh -p $PUERTO_REMOTO" -avz --delete $ARCHIVOS ${RUTA_DESTINO}/paginas/ 2>&1`
test $? -ne 0 && ERROR=1 && log "ATENCION: $RS_OUTPUT" -p
echo `date "+%d %b %r"`" -- MARK --" >> $ARCH_DEBUG
echo ${ARCHIVOS}: $RS_OUTPUT >> $ARCH_DEBUG
done
# Realiza el respaldo de "otros" archivos
# Si ocurre algun error se loguea
for ARCHIVOS in $OTROS
do
log "Actualizando \"${ARCHIVOS}\" en \"${RUTA_DESTINO}/OTROS/\""
RS_OUTPUT=`rsync -e "ssh -p $PUERTO_REMOTO" -avz --delete $ARCHIVOS ${RUTA_DESTINO}/OTROS/ 2>&1`
test $? -ne 0 && ERROR=1 && log "ATENCION: $RS_OUTPUT" -p
echo `date "+%d %b %r"`" -- MARK --" >> $ARCH_DEBUG
echo ${ARCHIVOS}: $RS_OUTPUT >> $ARCH_DEBUG
done
if [ $ERROR -eq 0 ];
then
if [ +$CONSERVAR_DEBUG == '+0' ];
then
rm $ARCH_DEBUG
else
log "El archivo de debug es \"${ARCH_DEBUG}\""
fi
fi
log "Backup finalizado"
logger -t $0 'Backup finalizado'
exit 0