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:
- Respaldo de todas las bases de datos MySQL: Utiliza
mysqldump
para generar respaldos de cada base de datos, excluyendo bases internas comomysql
,information_schema
y otras similares. - Compresión de respaldos: Comprime los archivos
.sql
generados para ahorrar espacio en disco. - Registro detallado en un archivo de log: Documenta cada paso del proceso para facilitar la auditoría y resolución de problemas.
- Transferencia a almacenamiento remoto: Copia los respaldos al directorio remoto especificado.
- Limpieza automática de respaldos antiguos: Elimina respaldos locales y remotos que exceden el período de retención definido.
- 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:
--login-path=respaldos
: Define un alias o nombre para la configuración (en este caso,respaldos
).--host=localhost
: Especifica el host al que se conectará MySQL.--user=tu_usuario
: Define el usuario de MySQL.--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!