Cada archivo de respaldo sigue esta estructura de nomenclatura:
[nombre_sin_extensión]_[timestamp].[extensión_original].bkp
Componentes:
- Nombre base: el nombre del archivo original sin su extensión
- Separador: guion bajo (_)
- Timestamp: fecha y hora en formato ISO:
YYYY-MM-DDTHH-MM-SS(zona horaria CST Ciudad de México, UTC-6) - Extensión original: se preserva la extensión del archivo original
- Extensión de respaldo: se añade
.bkpal final
Ejemplos de nomenclatura:
archivo.txt→archivo_2025-08-01T04-38-18.txt.bkpconfig.yaml→config_2025-08-01T04-38-18.yaml.bkpscript.sh→script_2025-08-01T04-38-18.sh.bkpdatabase.sql→database_2025-08-01T04-38-18.sql.bkp
Los respaldos deben almacenarse en una carpeta llamada «backups», creada según el contexto del proyecto o sistema.
Si se encuentra un archivo con extensión «.bak» o «.bkp» que no cumpla con los estándares establecidos, revisa su timestamp y actualiza el nombre para alinearlo con esta convención.
La inclusión de la hora garantiza nombres únicos y trazabilidad precisa, independientemente de la frecuencia de respaldos en el día.
Evita sobrescribir respaldos previos. La convención de fecha y hora permite conservar la secuencia histórica de cada copia.
Zona horaria obligatoria: todos los timestamps deben generarse usando la zona horaria CST de Ciudad de México (UTC-6). Nunca usar UTC ni la zona horaria local del sistema si es diferente a CST.
TZ="America/Mexico_City" en comandos date garantiza la conversión automática.
Esta política aplica a cualquier script o comando que realice operaciones de eliminación permanente de archivos, registros, configuraciones o cualquier otro tipo de datos.
Si la ejecución del script o comando es manual (iniciada por un usuario), el sistema deberá:
- Mostrar un mensaje de advertencia que indique que se realizará un borrado irreversible
- Preguntar explícitamente si se desea realizar un respaldo antes de continuar
- Permitir al usuario elegir entre las siguientes opciones:
- Realizar respaldo automático siguiendo la política de respaldos establecida
- Cancelar la ejecución
- Continuar sin respaldo (solo si se confirma dos veces)
Si la ejecución es automatizada (por cron jobs, pipelines, bots u otros procesos no interactivos):
- El script deberá verificar si existe una política de respaldo activa
- Deberá realizar un respaldo completo conforme a dicha política antes de iniciar cualquier operación destructiva
- Si el respaldo falla, el script no deberá continuar con el borrado. Deberá registrar el error y salir de forma segura
Toda acción de borrado deberá ser registrada con:
- Fecha y hora (formato 24 horas, zona horaria CST Ciudad de México, UTC-6)
- Usuario o proceso que inició la ejecución
- Resultado del respaldo
- Elementos afectados por el borrado
TZ="America/Mexico_City" date para garantizar que la fecha se calcule correctamente en CST (restando 6 horas a UTC), no solo agregando el sufijo CST.
- Implementar funciones de respaldo reutilizables en los scripts
- Utilizar variables de entorno para definir rutas de respaldo
- Incluir pruebas en entornos de staging antes de aplicar en producción
backups/
├── daily/ # Respaldos diarios automáticos (subcarpetas por fecha YYYY-MM-DD)
├── manual/ # Respaldos manuales por demanda (subcarpetas por fecha)
├── pre-deploy/ # Respaldos antes de despliegues
├── pre-delete/ # Respaldos antes de operaciones destructivas
└── archive/ # Respaldos antiguos comprimidos
Ejemplo con fecha del día (CST):
DATE_CST=$(TZ="America/Mexico_City" date +"%Y-%m-%d")
mkdir -p "backups/daily/${DATE_CST}"- Localiza el respaldo a restaurar y su archivo de checksum (.sha256 si existe).
- Verifica integridad antes de restaurar.
- Restaura preservando permisos cuando aplique y valida el resultado.
Ejemplo (archivo suelto):
# Verificación previa (si hay checksum)
sha256sum -c backups/daily/2025-08-18/archivo_2025-08-18T12-00-00.txt.bkp.sha256
# Restauración
cp backups/daily/2025-08-18/archivo_2025-08-18T12-00-00.txt.bkp ./archivo.txt
# Validación posterior (opcional)
sha256sum ./archivo.txtEjemplo (tar.zst):
# Verificar e inspeccionar
zstd -t archivo_2025-08-18T12-00-00.tar.zst
unzstd -c archivo_2025-08-18T12-00-00.tar.zst | tar -tvf -
# Restaurar en ruta destino
unzstd -c archivo_2025-08-18T12-00-00.tar.zst | tar -xvf - -C /ruta/destino- Política: generar .sha256 solo para respaldos grandes (tamaño >= 100 MB) para optimizar costo/tiempo.
- Umbral configurable:
BACKUP_SHA_THRESHOLD_BYTES(por defecto 104857600 = 100 MB).
- Umbral configurable:
- Los archivos con .sha256 deben verificarse siempre; los menores al umbral pueden verificarse bajo demanda.
- Verificación masiva:
find backups -type f -name "*.sha256" -exec sha256sum -c {} \;- Mejor relación/velocidad que gzip en muchos casos.
- Ejemplo para empaquetar y comprimir un archivo/directorio:
TS=$(TZ=America/Mexico_City date +"%Y-%m-%dT%H-%M-%S")
TARGET="mi_carpeta"
tar --mtime="$(date -d "$TS" +%Y-%m-%d)" --owner=0 --group=0 --numeric-owner -cf - "$TARGET" | zstd -T0 -19 -o "${TARGET}_${TS}.tar.zst"- Permite snapshots diarios con hardlinks a archivos no cambiados.
- Esquema:
BASE="/datos"
DEST="backups/daily"
DATE_CST=$(TZ=America/Mexico_City date +"%Y-%m-%d")
SNAP="$DEST/$DATE_CST"
LAST=$(ls -1 "$DEST" | sort | tail -n1)
mkdir -p "$SNAP"
if [ -n "$LAST" ] && [ "$LAST" != "$DATE_CST" ]; then
rsync -a --delete --link-dest="$DEST/$LAST" "$BASE/" "$SNAP/"
else
rsync -a --delete "$BASE/" "$SNAP/"
fi- Cifrado con age (recomendado) o gpg antes de enviar offsite.
- Ejemplo age:
age -r �RECIPIENT� -o backup.tar.zst.age backup.tar.zst- Subida offsite con rclone (S3/Backblaze/SSH):
rclone copy backups remote:bucket/path- Política 3-2-1: 3 copias, 2 medios, 1 offsite.
Ejemplo de unidades (ver carpeta systemd/backups/):
backup@.servicebackup@daily.timer
Variables recomendadas en el servicio:
- Environment=TZ=America/Mexico_City
- Logs a ruta fija en CST.
Formato sugerido de línea de log:
YYYY-MM-DD HH:MM:SS | acción | archivo | resultado | checksum
- Rotar backup.log y deletion.log periódicamente.
- Propietario/grupo: root:root para respaldos sensibles; permisos 0640.
- Añade backups/ al .gitignore del repositorio.
- SELinux: al restaurar en sistemas con SELinux, reetiquetar contextos:
restorecon -R /ruta/restaurada.
PostgreSQL (dump/restore):
# Dump
pg_dump --format=custom --no-owner --no-privileges "${PGDATABASE}" > "backups/daily/${DATE_CST}/db_${DATE_CST}.dump"
# Restore
pg_restore --clean --no-owner --no-privileges -d "${PGDATABASE}" "db_${DATE_CST}.dump"MySQL/MariaDB (dump/restore):
# Dump
mysqldump --single-transaction --routines --events "$MYSQL_DATABASE" > "backups/daily/${DATE_CST}/db_${DATE_CST}.sql"
# Restore
mysql "$MYSQL_DATABASE" < "db_${DATE_CST}.sql"# Uso: quick_bkp.sh archivo1 [archivo2 ...]
# Ejemplo: archivo.txt -> archivo_YYYY-MM-DD.txt.bkp
bash ~/rules/scripts/quick_bkp.sh archivo.txt#!/usr/bin/env bash
set -euo pipefail
log() {
printf "%s | %s\n" "$(TZ=America/Mexico_City date '+%Y-%m-%d %H:%M:%S')" "$*" | tee -a "${BACKUP_LOG_FILE:-backups/backup.log}"
}
# Función para crear respaldo con timestamp y checksum
create_backup() {
local source_file="$1"
local backup_dir="${2:-backups}"
local timestamp=$(TZ="America/Mexico_City" date +"%Y-%m-%dT%H-%M-%S")
local filename=$(basename "$source_file")
local name_without_ext="${filename%.*}"
local extension="${filename##*.}"
if [[ "$filename" == "$extension" ]]; then
local backup_name="${filename}_${timestamp}.bkp"
else
local backup_name="${name_without_ext}_${timestamp}.${extension}.bkp"
fi
mkdir -p "$backup_dir"
cp -a "$source_file" "$backup_dir/$backup_name"
(cd "$backup_dir" && sha256sum "$backup_name" > "$backup_name.sha256")
log "backup | $backup_dir/$backup_name | ok | $(awk '{print $1}' "$backup_dir/$backup_name.sha256")"
}
# Función para operaciones destructivas con confirmación
safe_delete() {
local target="$1"
echo "ADVERTENCIA: Se eliminará permanentemente: $target"
read -p "¿Desea crear un respaldo antes de continuar? (s/n): " -n 1 -r; echo
if [[ $REPLY =~ ^[SsYy]$ ]]; then
create_backup "$target" "backups/pre-delete"
else
read -p "¿Está seguro de continuar sin respaldo? (escriba 'CONFIRMAR'): " confirm
if [[ ${confirm:-} != "CONFIRMAR" ]]; then
echo "Operación cancelada"; return 1
fi
fi
rm -f "$target"
echo "$(TZ="America/Mexico_City" date '+%Y-%m-%d %H:%M:%S') - Eliminado: $target" >> backups/deletion.log
}export BACKUP_DIR="/path/to/backups"
export BACKUP_RETENTION_DAYS="30"
export BACKUP_COMPRESS_AFTER_DAYS="7"
export BACKUP_LOG_FILE="$BACKUP_DIR/backup.log"- Respaldos diarios: conservar por 30 días
- Respaldos manuales: conservar por 90 días
- Respaldos pre-deploy: conservar por 180 días
- Respaldos pre-delete: conservar permanentemente (archivar después de 1 año)
Respaldos mayores a 7 días deben comprimirse automáticamente para optimizar el espacio de almacenamiento:
# Comprimir respaldos antiguos
find backups/ -name "*.bkp" -mtime +7 -exec gzip {} \;# Eliminar respaldos expirados
find backups/daily/ -name "*.bkp*" -mtime +30 -delete
find backups/manual/ -name "*.bkp*" -mtime +90 -deleteElaborado por Rodrigo Álvarez (@incognia)