Automatización de Respaldos de Bases de Datos MySQL con Bash

Backups Bash Linux

En entornos de TI, asegurar la integridad y disponibilidad de la información es fundamental. Una tarea esencial para cualquier administrador de sistemas es implementar respaldos regulares de las bases de datos. En este artículo, veremos un script en Bash que automatiza el proceso de respaldo de bases de datos MySQL, asegurando eficiencia y confiabilidad.

Funcionalidades del Script

Este script cumple con varias tareas relacionadas con la gestión de respaldos:

  1. Respaldo de todas las bases de datos MySQL: Utiliza mysqldump para generar respaldos de cada base de datos, excluyendo bases internas como mysql, information_schema y otras similares.
  2. Compresión de respaldos: Comprime los archivos .sql generados para ahorrar espacio en disco.
  3. Registro detallado en un archivo de log: Documenta cada paso del proceso para facilitar la auditoría y resolución de problemas.
  4. Transferencia a almacenamiento remoto: Copia los respaldos al directorio remoto especificado.
  5. Limpieza automática de respaldos antiguos: Elimina respaldos locales y remotos que exceden el período de retención definido.
  6. Notificación a Zabbix: Reporta el estado del respaldo a través de zabbix_sender.

Uso de mysql_config_editor para Mayor Seguridad

El script utiliza mysql_config_editor para manejar las credenciales de MySQL de forma segura. Este enfoque elimina la necesidad de incluir contraseñas directamente en el código del script, reduciendo riesgos de seguridad.

¿Qué es mysql_config_editor?

mysql_config_editor es una herramienta que permite almacenar credenciales de acceso a MySQL en un archivo cifrado, conocido como el «archivo de login». Este archivo protege contraseñas y configuraciones sensibles, garantizando que no se expongan en texto claro.

El script utiliza una configuración preexistente almacenada bajo el alias respaldos. Esto está configurado previamente ejecutando el siguiente comando:

mysql_config_editor set --login-path=respaldos --host=localhost --user=tu_usuario --password

Este comando hace lo siguiente:

  1. --login-path=respaldos: Define un alias o nombre para la configuración (en este caso, respaldos).
  2. --host=localhost: Especifica el host al que se conectará MySQL.
  3. --user=tu_usuario: Define el usuario de MySQL.
  4. --password: Solicita interactivamente la contraseña para almacenarla de forma cifrada.

Una vez configurado, el script puede utilizar esta información sin necesidad de exponer las credenciales en texto plano:

DBs=$(mysql --login-path=respaldos -e "SHOW DATABASES;" | grep -v Database)

Este comando ejecuta la consulta para obtener todas las bases de datos utilizando las credenciales almacenadas bajo el alias respaldos.

Ventajas de mysql_config_editor

  • Seguridad mejorada: Las contraseñas no aparecen en los scripts ni en los logs del sistema.
  • Flexibilidad: Puedes configurar múltiples login-paths para diferentes servidores o usuarios.
  • Fácil de usar: La configuración es rápida y no interfiere con la ejecución de los scripts.

Desglose del Código

Configuración Inicial

El script inicia definiendo las variables principales, incluyendo los directorios de respaldo, configuración para Zabbix y los parámetros de retención.

BkDir="/Respaldos/respaldo-local" 
BkRemoto="/mnt/Respaldos/Bases/" 
Retencion=7 
ZabbixServer="xxx.xxx.xxx.xxx" 
ZabbixHost="mysql-server" 
ZabbixKey="estado_respaldo_mysql"

También registra información del sistema, como el hostname y la IP del servidor, para agregar contexto a los logs.

Registro Detallado con log_msg

La función log_msg es clave para capturar y registrar eventos durante la ejecución del script.

log_msg() { local msg="$1" local timestamp=$(date +'%d-%m-%Y %H:%M') echo "$timestamp - $msg" >> "$LogLocal" }

Cada paso del proceso se documenta en un archivo de log, lo que permite rastrear problemas en caso de errores.

Respaldo de Bases de Datos

El script lista las bases de datos disponibles en el servidor y las respalda, excluyendo las bases de datos internas de MySQL.

DBs=$(mysql --login-path=respaldos -e "SHOW DATABASES;" | grep -v Database) 
   for db in $DBs; do 
       if [ "$db" != "information_schema" ] && [ "$db" != "sys" ] && [ "$db" != "performance_schema" ] && [ "$db" != "mysql" ]; then 
          archivo_sql="$LogDir/$db.sql" 
          mysqldump --login-path=respaldos --single-transaction=TRUE --max_allowed_packet=512M --triggers --routines --events "$db" > "$archivo_sql" 
       fi 
   done

Ventajas de Automatizar los Respaldos

  • Seguridad: Usar mysql_config_editor elimina la exposición de credenciales en el script.
  • Reducción de errores humanos: Automatizar el proceso minimiza los riesgos de omisiones.
  • Ahorro de tiempo: Libera tiempo del equipo técnico para enfocarse en otras tareas críticas.
  • Auditoría y monitoreo: Los logs detallados y la integración con Zabbix facilitan la supervisión.

Script Completo

#!/bin/sh

# Configuración de variables
BkDir="/Respaldos/respaldo-local"
Fecha=$(date +'%d-%m-%Y')
FechaLog=$(date +'%d-%m-%Y %H:%M')
FechaDir=$(date +'%d-%m-%Y')  # Carpeta con formato de fecha dd-mm-yyyy
BkRemoto="/mnt/Respaldos/WCP-Bases/"
LogDir="$BkDir/$FechaDir"
LogLocal="$LogDir/backup_${Fecha}.log"
ZabbixSender="/usr/bin/zabbix_sender"
ZabbixServer="172.19.2.46"
ZabbixHost="pmysql01"
ZabbixKey="estado_respaldo_mysql"
Retencion=7
estado_respaldo=0

# Obtener información del sistema
Hostname=$(hostname)
IP=$(hostname -I | awk '{print $1}') # Obtiene la primera IP

# Función para registrar mensajes con fecha y hora
log_msg() {
    local msg="$1"
    local timestamp=$(date +'%d-%m-%Y %H:%M')
    echo "$timestamp - $msg" >> "$LogLocal"
}

# Inicializar el log
mkdir -p "$LogDir"
log_msg "Inicio del respaldo"

# Encabezado del log de bases de datos
{
    echo "=============================="
    echo "      INFORMACIÓN DEL EQUIPO"
    echo "=============================="
    echo "Hostname: $Hostname"
    echo "IP: $IP"
    echo "=============================="
    echo "Inicio del respaldo: $FechaLog"
    echo "=============================="
} > "$LogLocal"

# Realizar el respaldo
DBs=$(mysql --login-path=respaldos -e "SHOW DATABASES;" | grep -v Database)

for db in $DBs; do
    if [ "$db" != "information_schema" ] && [ "$db" != "sys" ] && [ "$db" != "performance_schema" ] && [ "$db" != "mysql" ] && [ "$db" != "_*" ]; then
        archivo_sql="$LogDir/$db.sql"

        # Realizar el respaldo y registrar el nombre del archivo
        mysqldump --login-path=respaldos --single-transaction=TRUE --max_allowed_packet=512M --triggers --routines --events "$db" > "$archivo_sql"
        if [ $? -eq 0 ]; then
            log_msg "Respaldo con exito para la base de datos: $db"
            log_msg "Archivo SQL: $archivo_sql"
        else
            log_msg "Error al realizar el respaldo para la base de datos: $db"
            estado_respaldo=1
            continue
        fi

        # Comprimir cada archivo .sql por separado
        archivo_respaldo_comprimido="$LogDir/respaldo_${db}_${Fecha}.sql.gz"
        gzip -c "$archivo_sql" > "$archivo_respaldo_comprimido"
        if [ $? -eq 0 ]; then
            log_msg "Respaldo comprimido con exito: $archivo_respaldo_comprimido"
        else
            log_msg "Error al comprimir el respaldo: $archivo_respaldo_comprimido"
            estado_respaldo=1
            continue
        fi

        # Eliminar el archivo SQL después de comprimir
        rm -f "$archivo_sql"
    fi
done

# Copiar la carpeta de respaldos al directorio remoto
log_msg "Copiando la carpeta de respaldos al remoto"
if ! mkdir -p "$BkRemoto/$FechaDir"; then
    log_msg "Error al crear el directorio remoto: $BkRemoto/$FechaDir"
    estado_respaldo=1
else
    # Usar cp -r en lugar de rsync
    if ! cp -r "$LogDir/"* "$BkRemoto/$FechaDir/"; then
        log_msg "Error al copiar la carpeta de respaldos al remoto."
        estado_respaldo=1
    else
        log_msg "Carpeta de respaldos copiada al remoto con éxito."
    fi
fi

# Limpieza local
log_msg "Iniciando limpieza de respaldos antiguos localmente"
find "$BkDir" -maxdepth 1 -type d -mtime +$Retencion -exec rm -rf {} \; >> $LogLocal 2>&1
find "$BkDir" -maxdepth 1 -type f -name "*.gz" -mtime +$Retencion -exec rm -f {} \; >> $LogLocal 2>&1

# Limpieza remota
log_msg "Iniciando limpieza de respaldos antiguos en el remoto"
find "$BkRemoto" -maxdepth 1 -type d -mtime +$Retencion -exec rm -rf {} \; >> $LogLocal 2>&1
find "$BkRemoto" -maxdepth 1 -type f -name "*.gz" -mtime +$Retencion -exec rm -f {} \; >> $LogLocal 2>&1

# Enviar el estado de salida a Zabbix si Zabbix Sender está disponible
if [ -x "$ZabbixSender" ]; then
    estado_zabbix="$estado_respaldo"
    if [ $estado_respaldo -eq 0 ]; then
        grep -q "Error" $LogLocal && estado_zabbix=1
    fi
    zabbix_output=$($ZabbixSender -z $ZabbixServer -s $ZabbixHost -k $ZabbixKey -o $estado_zabbix 2>&1)
    zabbix_status=$?
    log_msg "Respuesta de Zabbix Sender: $zabbix_output"
    log_msg "Estado de salida de Zabbix Sender: $zabbix_status"
    if [ $zabbix_status -ne 0 ]; then
        log_msg "Error al enviar el estado a Zabbix."
        estado_respaldo=1
    else
        log_msg "Estado de respaldo enviado a Zabbix con éxito."
    fi
else
    log_msg "Zabbix Sender no encontrado. No se puede enviar el estado a Zabbix."
    estado_respaldo=2
fi

# Finalizar el log
FechaFin=$(date +'%d-%m-%Y %H:%M')
log_msg "Proceso de respaldo completado: $FechaFin"
log_msg "Estado de salida enviado:  $estado_respaldo"

# Pie de página para los logs
{
    echo "=============================="
    echo "      RESUMEN DEL LOG"
    echo "=============================="
    echo "Errores encontrados: $(grep -c '^.*Error al.*$' "$LogLocal")"
    echo "Respaldos exitosos: $(grep -c 'con exito' "$LogLocal")"
    echo "=============================="
    echo "Fin del log: $(date +'%d-%m-%Y %H:%M')"
} >> "$LogLocal"

# Copiar el archivo de log al directorio remoto
if ! cp "$LogLocal" "$BkRemoto/$FechaDir/"; then
    log_msg "Error al copiar el archivo de log al remoto."
    estado_respaldo=1
fi


exit $estado_respaldo

 


Implementar herramientas como mysql_config_editor y automatizar procesos con scripts bien diseñados mejora significativamente la confiabilidad de los sistemas de respaldo. ¿Ya estás utilizando estas técnicas en tus entornos? ¡Cuéntanos en los comentarios!

 

 

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *