Volver al índice
root@vps-donweb:~/docs/backups$

Backups

herramientas mysqldump · rsync · tar
SO Ubuntu 22.04 LTS
categoría Infraestructura
REGLA 3-2-1 La estrategia de backup que funciona

La regla 3-2-1 es el estándar de la industria para backups confiables:

3  copias del dato
     → el original + 2 backups

2  tipos de soporte distintos
     → ej: disco del VPS + almacenamiento en la nube

1  copia offsite (fuera del servidor principal)
     → si el datacenter se cae, tus datos sobreviven

Un backup que solo existe en el mismo VPS no es un backup real — si el servidor muere, todo se va junto.

QUÉ RESPALDAR Inventario mínimo para un VPS web
CRÍTICO — perder esto es catastrófico:
  ✓ Bases de datos (MariaDB, PostgreSQL, SQLite)
  ✓ Archivos subidos por usuarios (/var/www/*/uploads)
  ✓ Variables de entorno y secretos (.env, secrets)
  ✓ Certificados SSL personalizados (no Let's Encrypt*)

IMPORTANTE — se puede reconstruir pero lleva tiempo:
  ✓ Código de la aplicación (si no está en Git)
  ✓ Configuraciones de Nginx (/etc/nginx/)
  ✓ Configuraciones de servicios (/etc/*)
  ✓ Crontabs (crontab -l)
  ✓ Volúmenes de Docker

PRESCINDIBLE — fácil de reinstalar:
  ✗ Paquetes del sistema (apt)
  ✗ node_modules, vendor, venv
  ✗ Caché, logs temporales
  ✗ Certificados de Let's Encrypt*

* Let's Encrypt se puede regenerar gratis en minutos con Certbot — no necesitás backupearlo. Sí hacer backup de configuraciones personalizadas de SSL.

FRECUENCIA Cuándo hacer cada tipo de backup
DIARIO   → bases de datos (son lo que más cambia)
           → archivos subidos por usuarios
           → retener por 7 días

SEMANAL  → configuraciones del sistema
           → código si no usás Git
           → retener por 4 semanas

MENSUAL  → snapshot completo del VPS (si el proveedor lo permite)
           → retener por 3-6 meses

ANTES DE → cualquier cambio grande en producción
  CAMBIOS   (deploy importante, migraciones, actualizaciones)

En Donweb VPS revisá si incluyen snapshots automáticos en el panel — pueden ser un complemento útil a tus backups propios.

MYSQLDUMP Backup de MariaDB / MySQL
# Exportar una base de datos
mysqldump -u root -p mi_base > mi_base.sql

# Con fecha en el nombre
mysqldump -u root -p mi_base > mi_base_$(date +%Y%m%d).sql

# Comprimido (ocupa hasta 10x menos)
mysqldump -u root -p mi_base | gzip > mi_base_$(date +%Y%m%d).sql.gz

# Todas las bases de datos
mysqldump -u root -p --all-databases | gzip > all_dbs_$(date +%Y%m%d).sql.gz

# Con opciones recomendadas para producción
mysqldump -u root -p \
  --single-transaction \
  --routines \
  --triggers \
  --events \
  --hex-blob \
  mi_base | gzip > mi_base_$(date +%Y%m%d_%H%M).sql.gz

--single-transaction hace el dump sin bloquear las tablas — esencial en producción con InnoDB para no interrumpir la app durante el backup.

SCRIPT Script de backup de todas las bases

Script que hace backup de cada base por separado, evitando las bases del sistema. Guardar en /usr/local/bin/backup-dbs.sh

#!/bin/bash
# backup-dbs.sh — backup de todas las bases de datos

BACKUP_DIR="/var/backups/mysql"
RETENTION_DAYS=7
DATE="$(date +%Y%m%d_%H%M)"
MYSQL_USER="root"
MYSQL_PASS="$(cat /etc/mysql/backup.pass)"  # contraseña en archivo

# Crear directorio si no existe
mkdir -p "$BACKUP_DIR"

# Listar bases (excluir las del sistema)
DATABASES=$(mysql -u"$MYSQL_USER" -p"$MYSQL_PASS" -e \
  "SHOW DATABASES;" 2>/dev/null | grep -Ev \
  "(Database|information_schema|performance_schema|mysql|sys)")

# Backup de cada base
for DB in $DATABASES; do
  echo "→ Backupeando: $DB"
  mysqldump -u"$MYSQL_USER" -p"$MYSQL_PASS" \
    --single-transaction --routines --triggers \
    "$DB" | gzip > "$BACKUP_DIR/${DB}_${DATE}.sql.gz"

  if [ ${PIPESTATUS[0]} -eq 0 ]; then
    echo "  ✓ $DB → ${DB}_${DATE}.sql.gz"
  else
    echo "  ✗ ERROR en $DB" >&2
  fi
done

# Eliminar backups más viejos que RETENTION_DAYS
find "$BACKUP_DIR" -name "*.sql.gz" \
  -mtime +"$RETENTION_DAYS" -delete
echo "Limpieza: eliminados backups de más de $RETENTION_DAYS días"
# Guardar la contraseña de MySQL en archivo con permisos restringidos
echo "tu_password_aqui" > /etc/mysql/backup.pass
chmod 600 /etc/mysql/backup.pass

# Dar permisos de ejecución al script
chmod +x /usr/local/bin/backup-dbs.sh

# Probar
/usr/local/bin/backup-dbs.sh
MARIABACKUP Backup en caliente (hot backup)

Para bases de datos grandes, mariabackup hace una copia física sin bloquear nada y soporta backups incrementales.

# Instalar
apt install mariadb-backup

# Backup completo
mariabackup --backup \
  --target-dir=/var/backups/mariadb/full \
  --user=root --password=tu_password

# Preparar el backup (necesario antes de restaurar)
mariabackup --prepare \
  --target-dir=/var/backups/mariadb/full

# Backup incremental (solo los cambios desde el último full)
mariabackup --backup \
  --target-dir=/var/backups/mariadb/inc1 \
  --incremental-basedir=/var/backups/mariadb/full \
  --user=root --password=tu_password

mariabackup es ideal cuando la base supera varios GB y el tiempo de mysqldump se vuelve un problema.

TAR Comprimir directorios con tar
# Comprimir directorio completo
tar czf backup_www_$(date +%Y%m%d).tar.gz /var/www/

# Excluir carpetas innecesarias
tar czf backup_www_$(date +%Y%m%d).tar.gz \
  --exclude=/var/www/*/node_modules \
  --exclude=/var/www/*/vendor \
  --exclude=/var/www/*/.git \
  --exclude=/var/www/*/storage/logs \
  /var/www/

# Backup de configuraciones del sistema
tar czf backup_etc_$(date +%Y%m%d).tar.gz \
  /etc/nginx/ \
  /etc/mysql/ \
  /etc/php/ \
  /etc/fail2ban/ \
  /etc/ufw/ \
  /etc/crontab \
  /var/spool/cron/

# Ver contenido de un tar sin extraer
tar tzf backup_www_20240101.tar.gz | head -30

# Extraer en directorio específico
tar xzf backup_www_20240101.tar.gz -C /tmp/restore/

# Opciones de tar:
#  c = crear   x = extraer   t = listar
#  z = gzip    j = bzip2     J = xz
#  f = archivo  v = verbose
RSYNC Sincronización incremental de archivos

rsync es mucho más eficiente que tar para backups frecuentes — solo transfiere lo que cambió.

# Sincronizar directorio local
rsync -av /var/www/ /var/backups/www/

# Con opciones recomendadas para backup
rsync -avz \
  --delete \
  --exclude='node_modules/' \
  --exclude='.git/' \
  --exclude='*.log' \
  /var/www/ /var/backups/www/

# Hacia servidor remoto via SSH
rsync -avz -e "ssh -p 2222 -i ~/.ssh/backup_key" \
  /var/www/ \
  backup_user@servidor-remoto.com:/backups/www/

# Desde servidor remoto hacia local (pull)
rsync -avz -e "ssh -p 2222" \
  backup_user@vps:/var/www/ \
  /backups/vps/www/

# Dry run — simular sin hacer cambios
rsync -avzn /var/www/ /var/backups/www/

# Opciones útiles:
#  -a = archive (permisos, timestamps, links, recursivo)
#  -v = verbose
#  -z = comprimir en tránsito
#  -n = dry run
#  --delete = eliminar en destino lo que no está en origen
#  --progress = mostrar progreso
ROTACIÓN Backups incrementales con rsync + hardlinks

Técnica que crea múltiples snapshots del tipo "Time Machine" — cada día parece un backup completo pero solo ocupa el espacio de los cambios, gracias a hardlinks.

#!/bin/bash
# backup-rotate.sh — 7 snapshots diarios sin duplicar datos

SRC="/var/www/"
DEST="/var/backups/snapshots"
DATE="$(date +%Y%m%d)"

# Si existe un backup de ayer, usarlo como base de hardlinks
LINK_DEST=""
YESTERDAY="$(ls -d $DEST/20* 2>/dev/null | tail -1)"
if [ -d "$YESTERDAY" ]; then
  LINK_DEST="--link-dest=$YESTERDAY"
fi

# Crear snapshot de hoy
rsync -az --delete \
  $LINK_DEST \
  --exclude='node_modules/' \
  --exclude='.git/' \
  "$SRC" "$DEST/$DATE/"

# Mantener solo los últimos 7 snapshots
ls -d $DEST/20* | head -n -7 | xargs rm -rf

echo "Snapshot $DATE completado"

Con hardlinks, 7 días de backups de un directorio de 5GB ocupan solo 5GB más los cambios incrementales — no 35GB.

S3 / R2 Backup a almacenamiento en la nube

AWS S3, Cloudflare R2, Backblaze B2 y similares son ideales como destino offsite. Se usan con la herramienta rclone o el CLI de AWS.

# Instalar rclone (soporta S3, R2, B2, GDrive, y más)
curl https://rclone.org/install.sh | sudo bash

# Configurar destino (interactivo)
rclone config
# → Seguir los pasos para S3/R2/B2
# → El perfil queda guardado en ~/.config/rclone/rclone.conf

# Subir backup al bucket
rclone copy /var/backups/mysql/ remote:mi-bucket/mysql/

# Sincronizar (elimina en destino lo que no está en origen)
rclone sync /var/backups/ remote:mi-bucket/vps-backups/

# Con progreso y log
rclone copy /var/backups/mysql/ remote:mi-bucket/mysql/ \
  --progress \
  --log-file=/var/log/rclone-backup.log

# Listar contenido del bucket
rclone ls remote:mi-bucket/mysql/

# Verificar integridad (checksum)
rclone check /var/backups/mysql/ remote:mi-bucket/mysql/

Cloudflare R2 tiene egress gratuito (no cobra por descargar los backups). Backblaze B2 tiene 10GB gratis. Ambas son alternativas más baratas que S3 para backups.

SSH / SCP Backup a otro servidor via SSH
# Clave SSH dedicada para backups (sin passphrase para automatizar)
ssh-keygen -t ed25519 -f ~/.ssh/id_backup -N "" -C "backup-key"
ssh-copy-id -i ~/.ssh/id_backup.pub backup@servidor-remoto.com

# Copiar backup al servidor remoto
scp -i ~/.ssh/id_backup \
  /var/backups/mysql/mi_base_$(date +%Y%m%d).sql.gz \
  backup@servidor-remoto.com:/backups/mysql/

# Rsync al servidor remoto (incremental)
rsync -avz \
  -e "ssh -i ~/.ssh/id_backup -p 22" \
  /var/backups/ \
  backup@servidor-remoto.com:/backups/vps/

# Crear usuario restringido en el servidor destino
useradd -m -s /bin/rbash backup
mkdir -p /backups
chown backup:backup /backups

Usar una clave SSH dedicada sin passphrase solo para backups — con permisos mínimos en el servidor destino (solo escritura en la carpeta de backups).

ENCRIPTACIÓN Proteger los backups

Si los backups contienen datos sensibles y se envían a la nube, encriptarlos antes de subir.

# Encriptar con GPG (clave simétrica)
gpg --symmetric \
  --cipher-algo AES256 \
  --batch \
  --passphrase "frase_muy_segura" \
  mi_base_20240101.sql.gz
# Genera: mi_base_20240101.sql.gz.gpg

# Desencriptar
gpg --decrypt \
  --batch \
  --passphrase "frase_muy_segura" \
  mi_base_20240101.sql.gz.gpg > mi_base_20240101.sql.gz

# rclone puede encriptar automáticamente
# Configurar un remote de tipo "crypt" sobre el bucket
rclone config
# → New remote → Type: crypt → Remote: mi-bucket
# → rclone crypt encripta antes de subir, desencripta al bajar

# Una vez configurado, usarlo igual que cualquier remote
rclone copy /var/backups/ crypt-remote:backups/

Guardá la passphrase de encriptación en un lugar seguro FUERA del servidor. Si la perdés, los backups son irrecuperables.

SCRIPT MAESTRO Script completo de backup diario

Un script que lo hace todo: backup de bases de datos, archivos, y sube a la nube. Guardar en /usr/local/bin/backup-diario.sh

#!/bin/bash
# backup-diario.sh — backup completo del VPS

set -euo pipefail   # salir si hay errores

## ── CONFIGURACIÓN ─────────────────────────
BACKUP_DIR="/var/backups/diario"
DATE="$(date +%Y%m%d_%H%M)"
RETENTION=7              # días a retener
LOG="/var/log/backup.log"
EMAIL="tu@email.com"
MYSQL_PASS="$(cat /etc/mysql/backup.pass)"
REMOTE="r2:mi-bucket/vps"  # rclone remote

## ── FUNCIONES ──────────────────────────────
log() { echo "[$(date '+%H:%M:%S')] $*" | tee -a "$LOG"; }
ok()  { echo "[$(date '+%H:%M:%S')] ✓ $*" | tee -a "$LOG"; }
err() { echo "[$(date '+%H:%M:%S')] ✗ $*" | tee -a "$LOG" >&2; }

mkdir -p "$BACKUP_DIR/mysql" "$BACKUP_DIR/www" "$BACKUP_DIR/etc"
log "=== Backup iniciado: $DATE ==="

## ── 1. BASES DE DATOS ──────────────────────
log "Exportando bases de datos..."
DATABASES=$(mysql -uroot -p"$MYSQL_PASS" -e "SHOW DATABASES;" 2>/dev/null \
  | grep -Ev "(Database|information_schema|performance_schema|mysql|sys)")

for DB in $DATABASES; do
  mysqldump -uroot -p"$MYSQL_PASS" \
    --single-transaction --routines --triggers \
    "$DB" 2>/dev/null \
    | gzip > "$BACKUP_DIR/mysql/${DB}_${DATE}.sql.gz" \
    && ok "$DB" || err "$DB falló"
done

## ── 2. ARCHIVOS WEB ────────────────────────
log "Sincronizando /var/www..."
rsync -az --delete \
  --exclude='node_modules/' \
  --exclude='vendor/' \
  --exclude='.git/' \
  --exclude='*.log' \
  /var/www/ "$BACKUP_DIR/www/" \
  && ok "www" || err "www falló"

## ── 3. CONFIGURACIONES ─────────────────────
log "Backupeando configuraciones..."
tar czf "$BACKUP_DIR/etc/etc_${DATE}.tar.gz" \
  /etc/nginx/ /etc/mysql/ /etc/php/ \
  /etc/fail2ban/ /etc/ufw/ \
  2>/dev/null \
  && ok "etc" || err "etc falló"

# Guardar crontabs
crontab -l > "$BACKUP_DIR/etc/crontab_root_${DATE}.txt" 2>/dev/null || true

## ── 4. SUBIR A LA NUBE ─────────────────────
log "Subiendo a $REMOTE..."
rclone sync "$BACKUP_DIR/" "$REMOTE/" \
  --log-file="$LOG" \
  && ok "subida completada" || err "subida falló"

## ── 5. LIMPIEZA LOCAL ──────────────────────
find "$BACKUP_DIR/mysql" -name "*.sql.gz" \
  -mtime +"$RETENTION" -delete
find "$BACKUP_DIR/etc"   -name "*.tar.gz" \
  -mtime +"$RETENTION" -delete
log "Limpieza: eliminados archivos de más de $RETENTION días"

## ── 6. REPORTE ─────────────────────────────
SIZE=$(du -sh "$BACKUP_DIR" | cut -f1)
log "=== Backup completado. Tamaño: $SIZE ==="
tail -20 "$LOG" | mail -s "✓ Backup VPS OK — $DATE" "$EMAIL"
chmod +x /usr/local/bin/backup-diario.sh

# Probar manualmente antes de automatizar
/usr/local/bin/backup-diario.sh
CRON Programar backups automáticos
# Editar crontab de root
crontab -e

# Backup diario a las 2:00 AM
0 2 * * * /usr/local/bin/backup-diario.sh

# Backup de base de datos cada 6 horas
0 */6 * * * /usr/local/bin/backup-dbs.sh

# Backup de configuraciones los domingos a las 3 AM
0 3 * * 0 tar czf /var/backups/etc/etc_$(date +\%Y\%m\%d).tar.gz /etc/nginx/ /etc/mysql/

# Verificar que el backup se hizo (alertar si no hay archivo de hoy)
30 8 * * * /usr/local/bin/verificar-backups.sh

Las % en crontab necesitan escaparse como \%. O mejor: ponerlas dentro del script y llamar solo al script desde cron.

SYSTEMD Timer de systemd (alternativa a cron)

Los timers de systemd son más robustos que cron — tienen logs integrados, manejo de errores y pueden recuperar ejecuciones perdidas.

# /etc/systemd/system/backup.service
[Unit]
Description=Backup diario del VPS
After=network.target mysql.service

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup-diario.sh
User=root
StandardOutput=journal
StandardError=journal
# /etc/systemd/system/backup.timer
[Unit]
Description=Timer de backup diario

[Timer]
OnCalendar=*-*-* 02:00:00   # todos los días a las 2 AM
Persistent=true             # ejecutar si el servidor estaba apagado
RandomizedDelaySec=5min     # variar un poco para no sobrecargar

[Install]
WantedBy=timers.target
systemctl daemon-reload
systemctl enable backup.timer
systemctl start  backup.timer

# Ver próxima ejecución
systemctl list-timers backup.timer

# Ver logs del último backup
journalctl -u backup.service -n 50

Persistent=true es la gran ventaja sobre cron — si el servidor estaba apagado a las 2 AM, el backup se ejecuta la próxima vez que arranque.

RESTAURAR DB Recuperar bases de datos
# Restaurar desde dump sin comprimir
mysql -u root -p mi_base < mi_base_20240101.sql

# Restaurar desde dump comprimido
gunzip < mi_base_20240101.sql.gz | mysql -u root -p mi_base
zcat mi_base_20240101.sql.gz    | mysql -u root -p mi_base

# Si la base no existe, crearla primero
mysql -u root -p -e "CREATE DATABASE mi_base CHARACTER SET utf8mb4;"
gunzip < mi_base_20240101.sql.gz | mysql -u root -p mi_base

# Restaurar solo una tabla específica del dump
gunzip < mi_base_20240101.sql.gz \
  | grep -A 1000 "CREATE TABLE \`usuarios\`" \
  | grep -B 1000 "CREATE TABLE \`" \
  | head -n -1 \
  | mysql -u root -p mi_base

# Restaurar con mariabackup
systemctl stop mariadb
mariabackup --copy-back \
  --target-dir=/var/backups/mariadb/full
chown -R mysql:mysql /var/lib/mysql
systemctl start mariadb
RESTAURAR ARCHIVOS Recuperar desde tar o rsync
# Ver contenido del backup antes de restaurar
tar tzf backup_www_20240101.tar.gz | grep "mi-sitio"

# Restaurar archivo o directorio específico del tar
tar xzf backup_www_20240101.tar.gz \
  -C / \
  var/www/mi-sitio/uploads/foto.jpg

# Restaurar directorio completo en ubicación alternativa
tar xzf backup_www_20240101.tar.gz \
  -C /tmp/restauracion/

# Comparar antes de sobreescribir
diff -rq /tmp/restauracion/var/www/mi-sitio/ \
         /var/www/mi-sitio/

# Restaurar desde snapshot de rsync
rsync -av \
  /var/backups/snapshots/20240101/mi-sitio/ \
  /var/www/mi-sitio/

# Bajar backup desde la nube con rclone
rclone copy r2:mi-bucket/vps/www/ /var/www/
RESTAURAR CONFIGURACIONES Recuperar /etc y servicios
# Extraer configuraciones del tar
tar xzf backup_etc_20240101.tar.gz -C /tmp/etc-restore/

# Restaurar configuración de Nginx
cp -r /tmp/etc-restore/etc/nginx/ /etc/nginx/
nginx -t && systemctl reload nginx

# Restaurar crontab
crontab /var/backups/etc/crontab_root_20240101.txt

# Restaurar configuración de MySQL
cp /tmp/etc-restore/etc/mysql/mariadb.conf.d/50-server.cnf \
   /etc/mysql/mariadb.conf.d/
systemctl restart mariadb

Al restaurar configuraciones sobre un sistema en producción, siempre verificar la sintaxis antes de recargar el servicio.

VERIFICAR Un backup no verificado no es un backup

El paso más ignorado y el más importante. Verificar regularmente que los backups son válidos y restaurables.

# Verificar integridad de archivo comprimido
gunzip -t mi_base_20240101.sql.gz && echo "OK" || echo "CORRUPTO"
gzip   -t backup_www_20240101.tar.gz && echo "OK" || echo "CORRUPTO"

# Verificar que el SQL tiene contenido real
gunzip -c mi_base_20240101.sql.gz | head -20
gunzip -c mi_base_20240101.sql.gz | grep "CREATE TABLE" | wc -l

# Verificar tamaño mínimo (un backup de 0 bytes es una señal de error)
ls -lh /var/backups/mysql/*.sql.gz

# Restauración de prueba en base temporal
mysql -u root -p -e "CREATE DATABASE test_restore;"
gunzip < mi_base_20240101.sql.gz | mysql -u root -p test_restore
mysql -u root -p test_restore -e "SHOW TABLES; SELECT COUNT(*) FROM usuarios;"
mysql -u root -p -e "DROP DATABASE test_restore;"

# Verificar subida a la nube
rclone check /var/backups/mysql/ r2:mi-bucket/vps/mysql/
SCRIPT Verificación automática de backups

Script que verifica cada mañana que el backup de anoche se hizo y no está corrupto. Guardar en /usr/local/bin/verificar-backups.sh

#!/bin/bash
# verificar-backups.sh

BACKUP_DIR="/var/backups/diario/mysql"
EMAIL="tu@email.com"
MIN_SIZE_KB=10    # tamaño mínimo esperado en KB
ERRORES=0
REPORTE=""

# Verificar que existe backup de hoy
HOY="$(date +%Y%m%d)"
BACKUPS_HOY="$(ls $BACKUP_DIR/*${HOY}*.sql.gz 2>/dev/null | wc -l)"

if [ "$BACKUPS_HOY" -eq 0 ]; then
  REPORTE+="✗ No se encontraron backups de hoy ($HOY)\n"
  ERRORES=$(( ERRORES + 1 ))
fi

# Verificar integridad de cada backup de hoy
for FILE in $BACKUP_DIR/*${HOY}*.sql.gz; do
  [ -f "$FILE" ] || continue
  NAME="$(basename $FILE)"

  # Verificar tamaño mínimo
  SIZE_KB="$(du -k "$FILE" | cut -f1)"
  if [ "$SIZE_KB" -lt "$MIN_SIZE_KB" ]; then
    REPORTE+="✗ $NAME — demasiado pequeño (${SIZE_KB}KB)\n"
    ERRORES=$(( ERRORES + 1 ))
    continue
  fi

  # Verificar integridad del gzip
  if gunzip -t "$FILE" 2>/dev/null; then
    REPORTE+="✓ $NAME (${SIZE_KB}KB) — OK\n"
  else
    REPORTE+="✗ $NAME — CORRUPTO\n"
    ERRORES=$(( ERRORES + 1 ))
  fi
done

# Enviar reporte
if [ "$ERRORES" -gt 0 ]; then
  echo -e "$REPORTE" | mail -s "⚠ ERROR en backups VPS" "$EMAIL"
else
  echo -e "$REPORTE" | mail -s "✓ Backups VPS OK — $HOY" "$EMAIL"
fi
chmod +x /usr/local/bin/verificar-backups.sh

# Agregar a crontab — verificar a las 8 AM (backup corre a las 2 AM)
# 30 8 * * * /usr/local/bin/verificar-backups.sh
DRILL Simulacro de recuperación

Una vez al mes, practicar la restauración completa en un ambiente de prueba. Si nunca lo hiciste, no sabés si tus backups realmente funcionan.

# Checklist del simulacro mensual:

1. Bajar el último backup desde la nube
   rclone copy r2:mi-bucket/vps/ /tmp/drill/

2. Verificar integridad de todos los archivos
   find /tmp/drill -name "*.gz" -exec gunzip -t {} \; -print

3. Restaurar la base en una instancia de prueba
   mysql -u root -p -e "CREATE DATABASE drill_test;"
   gunzip < /tmp/drill/mysql/mi_base_*.sql.gz \
     | mysql -u root -p drill_test

4. Verificar que los datos son correctos
   mysql -u root -p drill_test \
     -e "SHOW TABLES; SELECT COUNT(*) FROM usuarios;"

5. Medir el tiempo de recuperación (RTO)
   time gunzip < backup.sql.gz | mysql -u root -p drill_test

6. Limpiar
   mysql -u root -p -e "DROP DATABASE drill_test;"
   rm -rf /tmp/drill/

# Documentar:
#   ¿Cuánto tiempo tomó restaurar?
#   ¿Hubo errores?
#   ¿Los datos eran coherentes?

Conocer el RTO (Recovery Time Objective) real de tu setup es tan importante como tener el backup. En una emergencia no es momento para descubrir que algo no funciona.