informe-diario.sh ya cumple las siete propiedades de una tarea desatendida. Vamos a aplicar esa técnica a la operación que más se agradece tener automatizada y peor se lleva improvisar. Un respaldo tiene una particularidad incómoda: es la única tarea del servidor cuyo valor solo se comprueba el día que todo lo demás ha fallado. Hasta ese día, un respaldo roto y uno bueno se parecen mucho —los dos generan ficheros, los dos ocupan disco, los dos escriben «ok» en el log—. Esta lección va de qué copiar, cómo copiarlo sin gastar un disco entero cada día, cómo retener las copias y, sobre todo, de la parte que casi nadie prueba hasta que la necesita: la restauración.
Contenido
- Qué respaldar, la regla 3-2-1 y RPO/RTO
- Completa, incremental y diferencial
tar: la copia completa comprimidarsync: la herramienta central--link-dest: incrementales que se restauran como completas- Rotación y retención
- Verificación y restauración
- Bases de datos, cifrado y espacio en disco
- Aplicación: nace
respaldo.sh
- Qué respaldar, la regla 3-2-1 y RPO/RTO
El primer error de un respaldo es querer copiarlo todo. El sistema entero produce ficheros enormes, lentos de generar y de restaurar, y en su mayor parte reproducibles: si el servidor arde, no vas a restaurar /usr/bin, vas a instalar Ubuntu 24.04 otra vez. Lo que hay que respaldar son las tres categorías que no se pueden reconstruir:
| Categoría | En srv-veloz-01 |
Por qué |
|---|---|---|
| Datos | /srv/veloz/datos/envios.csv, datos/historico/ |
Únicos e irrecuperables |
| Configuración | ~/veloz-ops/etc/, el crontab, unidades de systemd |
Reconstruible, pero costaría horas y saldría distinta |
| Estado | Volcados de base de datos, claves, certificados | Irrecuperable o caro de regenerar |
Y lo que no se respalda: el sistema operativo, los paquetes, las cachés, los temporales, los logs antiguos y muy especialmente el propio directorio de respaldos (copiarlo dentro duplica el tamaño en cada vuelta). Un criterio práctico: pregúntate cuánto tardarías en volver a tener ese fichero si desapareciera. Si la respuesta es «lo descargo otra vez», no va al respaldo; si es «no puedo», va el primero. La regla 3-2-1 es el consenso del sector y se recuerda sola: 3 copias de los datos (la original y dos respaldos), en 2 medios o sistemas distintos, con 1 de ellas fuera del emplazamiento. Cada número responde a un modo de fallo real: dos copias en el mismo disco mueren con el disco; dos en el mismo edificio mueren con el incendio o con el cifrado por ransomware que recorre la red. La copia remota es la que salva de la catástrofe, y por eso en 07-06 la enviaremos a srv-veloz-02 por SSH.
Los otros dos conceptos se explican con dos preguntas concretas, sin jerga. RPO (Recovery Point Objective): ¿cuántos datos puedo permitirme perder? Determina cada cuánto hago la copia. RTO (Recovery Time Objective): ¿cuánto puedo estar sin servicio? Determina cómo la hago. Si Veloz Envíos acepta perder como mucho un día de registros, el RPO es de 24 horas y basta una copia diaria; si el negocio no puede estar más de dos horas parado, ese RTO descarta un formato de respaldo que tarde tres en restaurarse. Estos dos números se deciden antes de escribir el script, porque determinan el diseño entero.
- Completa, incremental y diferencial
| Tipo | Qué copia | Espacio | Tiempo de copia | Restauración |
|---|---|---|---|---|
| Completa | Todo, cada vez | Máximo | Máximo | La más simple: una sola copia |
| Incremental | Lo cambiado desde la copia anterior | Mínimo | Mínimo | La completa + todas las incrementales en orden |
| Diferencial | Lo cambiado desde la última completa | Medio, creciente | Medio | La completa + la última diferencial |
Con una completa el domingo e incrementales de lunes a sábado, restaurar el estado del sábado exige recuperar siete piezas en el orden correcto; si falta la del miércoles, la cadena se rompe. Con diferenciales bastan dos piezas, a cambio de que cada una sea mayor que la anterior. La estrategia clásica es completa semanal más incrementales diarias, pero hay una cuarta opción que hoy es la mejor para ficheros y que veremos en el apartado 5: rsync --link-dest da copias que se generan como incrementales y se restauran como completas.
tar: la copia completa comprimida
tar: la copia completa comprimidaRetomando 05-01, tar empaqueta un árbol de directorios en un solo fichero comprimible:
fecha=$(date +%F) # 2026-08-03
tar czf "/respaldos/historico-$fecha.tar.gz" \
--exclude-from=~/veloz-ops/etc/respaldo.exclude -C /srv/veloz/datos historicoc crea, z comprime con gzip, f da el nombre. El -C /srv/veloz/datos es importante: cambia de directorio antes de empaquetar, así que dentro del archivo las rutas son historico/2026/08/… y no srv/veloz/datos/historico/…. Rutas relativas dentro del archivo significa poder restaurar donde quieras; con rutas absolutas te arriesgas a sobrescribir el original al descomprimir. El nombre con fecha es obligatorio para poder rotar, y siempre en formato %F, que ordena alfabéticamente igual que cronológicamente —cosa que 03-08-2026 no hace—.
Las exclusiones van en un fichero versionado, un patrón por línea (*.tmp, cache/, logs/*.gz), no incrustadas en el script: así se cambian sin tocar código. Para archivos grandes, --zstd comprime parecido a gzip pero mucho más rápido; -j (bzip2) y -J (xz) comprimen más a costa de CPU.
rsync: la herramienta central
rsync: la herramienta centraltar sirve para congelar un árbol en un fichero. Para sincronizar un directorio con su copia, la herramienta es rsync, y su virtud es que transfiere solo lo que ha cambiado.
| Opción | Qué hace | Nota |
|---|---|---|
-a |
Modo archivo: recursivo, preserva permisos, dueños, fechas y enlaces | La opción base, siempre |
-v / -z |
Detalla lo que copia / comprime al transferir | -v solo a mano; -z solo por red |
--delete |
Borra en el destino lo que ya no está en el origen | Peligrosa, ver abajo |
--dry-run / -n |
Simula sin tocar nada | Obligatoria antes de --delete |
--exclude PATRON |
Excluye rutas | Repetible; --exclude-from para listas |
--partial --progress |
Conserva lo transferido si se corta, y muestra avance | Para transferencias grandes |
--link-dest DIR |
Enlaza duro lo no modificado desde otra copia | El apartado 5 |
-e ssh |
Transporta por SSH | Destino remoto (07-06) |
La barra final decide el significado, y es el error clásico: rsync -a /srv/veloz/datos/ /respaldos/datos/ copia el contenido de datos, mientras que sin la barra del origen crea /respaldos/datos/datos/. Ponla siempre y sé consistente. Y --delete merece una advertencia seria. Hace que el destino sea un espejo exacto del origen, y eso significa que un borrado accidental en el origen se propaga al respaldo en la siguiente ejecución: si alguien borra envios.csv y a las 03:00 se ejecuta el respaldo, tu copia también lo pierde. Dos reglas: --delete solo tiene sentido cuando hay varias copias retenidas (apartado 6), de modo que la de ayer conserve lo borrado hoy; y nunca se estrena sin verlo antes.
Si esa lista de borrados te sorprende, todavía no estás listo para quitar el --dry-run.
--link-dest: incrementales que se restauran como completas
--link-dest: incrementales que se restauran como completasEste es el truco central del respaldo moderno de ficheros. Un enlace duro es un segundo nombre para los mismos datos en disco: dos rutas, un solo contenido, ocupación de una sola copia. --link-dest DIR le dice a rsync: «al copiar, compara cada fichero con el que hay en DIR; si no ha cambiado, en vez de copiarlo crea un enlace duro».
rsync -a --delete --link-dest=/respaldos/2026-08-02 /srv/veloz/datos/ /respaldos/2026-08-03/datos/
du -sh /respaldos/2026-08-02 /respaldos/2026-08-03; du -sh --total /respaldos/El resultado es notable: /respaldos/2026-08-03/ parece una copia completa —tiene todos los ficheros, se restaura copiando y sin reconstruir cadenas, y puedes borrar cualquier día sin afectar a los demás—, pero en disco solo ocupa lo que cambió respecto al anterior. Cada copia «pesa» 2,1 GB por separado, y las dos juntas ocupan 2,2 GB porque los ficheros compartidos se cuentan una vez. Treinta días de respaldos diarios pueden ocupar poco más que uno solo.
Dos avisos. Los enlaces duros exigen que ambas copias estén en el mismo sistema de ficheros: entre discos distintos --link-dest no falla, simplemente hace copias completas y llena el disco. Y como los ficheros están compartidos, modificar un fichero dentro de un respaldo lo modifica en todos los que lo comparten: los directorios de respaldo son de solo lectura, se restauran copiando fuera y jamás se editan en el sitio.
- Rotación y retención
Sin retención, el disco se llena y el respaldo deja de funcionar justo cuando más lo necesitas. La política habitual es GFS (grandfather-father-son): copias con densidad decreciente hacia el pasado —7 diarias (la última semana, día a día), 4 semanales (el último mes) y 6 mensuales (el último medio año)—. Son 17 copias en lugar de 180, y sigue permitiendo recuperar «como estaba el 3 de agosto» o «como estaba en marzo». La razón de conservar copias antiguas no es el fallo de disco —para eso basta la de ayer— sino el daño silencioso: un fichero corrupto o borrado que nadie nota hasta dos meses después.
find /respaldos/diarios -mindepth 1 -maxdepth 1 -type d -mtime +7 -exec rm -rf {} + # por fecha (05-01)
# Mas robusto: por nombre, que al ser AAAA-MM-DD ordena bien
mapfile -t copias < <(find /respaldos/diarios -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | sort -r)
(( ${#copias[@]} > 7 )) || { veloz_log_info "solo ${#copias[@]} copias; no toco nada"; return 0; }
for (( i = 7; i < ${#copias[@]}; i++ )); do
veloz_log_info "retencion: elimino ${copias[i]}"
rm -rf "/respaldos/diarios/${copias[i]}"
doneEn el primero, -mindepth 1 evita que find considere el propio directorio raíz, -maxdepth 1 no entra dentro de cada copia y -exec … + agrupa los borrados. Pero -mtime depende de la fecha del sistema de ficheros, que es frágil (un touch o una copia mal hecha la altera); como los nombres llevan fecha ISO, contar por nombre con sort -r es más fiable. Y fíjate en la salvaguarda de la línea del (( )): nunca sobra, porque el peor fallo posible de un script de retención es borrarlo todo.
- Verificación y restauración
Un fichero de 2 GB con el nombre correcto puede estar vacío por dentro, truncado por falta de disco o corrupto. Que el script haya terminado con código 0 no prueba que la copia sirva. Hay tres niveles, de más barato a más caro:
tar -tzf /respaldos/historico-2026-08-03.tar.gz > /dev/null || veloz_log_error "archivo corrupto"
sha256sum respaldo.tar.gz > respaldo.tar.gz.sha256 # guardar la suma JUNTO al respaldo
sha256sum -c respaldo.tar.gz.sha256 # comprobarla meses despues, o tras copiarlotar -t lista el contenido sin extraer y, al recorrerlo entero, gzip valida su suma interna: barato, y detecta truncados y corrupción. El fichero .sha256 permite comprobar mucho después que el archivo no se ha degradado y que llegó íntegro a otra máquina. Añade una comprobación de sentido común que detecta el fallo más frecuente: (( $(stat -c %s "$destino") > 1024 )), porque un respaldo que ayer ocupaba 2 GB y hoy 40 KB no es un respaldo pequeño, es un respaldo vacío con un fallo silencioso detrás.
El tercer nivel es el único que demuestra algo. La pregunta que revela si un sistema de respaldo funciona no es «¿se hacen las copias?», es «¿cuándo fue la última vez que restaurasteis una?». La restauración de prueba se hace siempre a un directorio temporal, nunca sobre los datos vivos: extraer sobre el original es la forma más rápida de convertir un incidente en un desastre, porque si el respaldo estaba corrupto acabas de destruir también lo que quedaba.
prueba=$(mktemp -d /tmp/restauracion.XXXXXX)
tar xzf /respaldos/historico-2026-08-03.tar.gz -C "$prueba"
diff -r "$prueba/historico/2026/08" /srv/veloz/datos/historico/2026/08 && echo "verificada"
rm -rf "$prueba"Para restaurar solo una parte se añade la ruta interna al final del tar xzf. Y desde una copia hecha con rsync, restaurar es copiar en sentido contrario —sin --delete, para no borrar en el destino lo creado después—: rsync -a /respaldos/diarios/2026-08-03/datos/ /srv/veloz/datos/. El procedimiento debe estar escrito donde se pueda leer sin acceso al servidor caído: los comandos exactos, en qué orden, qué servicio parar antes y cómo verificar después. Un runbook de restauración que solo existe en la cabeza de una persona no existe.
- Bases de datos, cifrado y espacio en disco
Bases de datos. Copiar /var/lib/mysql con el servicio en marcha produce un respaldo inconsistente: mientras rsync recorre los ficheros, el motor está escribiendo en varios a la vez, y acabas con una foto donde unas partes son de las 03:00:01 y otras de las 03:00:47. Puede parecer que funciona y fallar meses después al restaurar. La forma correcta es pedirle al motor una copia consistente:
mysqldump --single-transaction --routines veloz | gzip > "$destino/veloz-$fecha.sql.gz"
pg_dump -Fc veloz > "$destino/veloz-$fecha.dump"--single-transaction toma la instantánea dentro de una transacción, sin bloquear escrituras; -Fc genera un formato comprimido que permite restaurar tablas sueltas. El volcado es luego un fichero normal que ya puedes comprimir, verificar, retener y enviar fuera. Las credenciales van en ~/.my.cnf o ~/.pgpass con permisos 600, nunca en la línea de comandos, que es visible en ps para cualquier usuario.
Cifrado. Una copia que sale del servidor lleva datos de clientes fuera de tu control. Cifrarla es una línea: gpg --batch --symmetric --cipher-algo AES256 --passphrase-file "$BASE/etc/respaldo.key" -o "$destino.gpg" "$destino". El --batch evita cualquier pregunta interactiva (propiedad 1 de 07-02). Y aquí está la trampa: si pierdes la clave, pierdes el respaldo. Guardarla solo en el servidor que respaldas es inútil —arde con él—; ponerla junto al respaldo cifrado es peor que no cifrar. La clave va a un gestor de secretos o a un sobre físico, fuera del sistema (08-03).
Espacio en disco. Un respaldo que se queda sin espacio a la mitad deja un archivo truncado que parece válido. Comprueba antes, con lo de 06-03:
necesario=$(du -sk /srv/veloz/datos | cut -f1)
libre=$(df -P /respaldos | awk 'NR == 2 { print $4 }')
(( libre >= necesario * 12 / 10 )) || veloz_morir 74 "espacio insuficiente: $libre KB libres"df -P fuerza el formato POSIX de una línea por sistema de ficheros, evitando que un nombre largo parta la salida en dos. El margen del 20 % cubre la variación entre origen y copia. Si no cabe, la reacción correcta es fallar antes de empezar, no morir a la mitad.
- Aplicación: nace
respaldo.sh
respaldo.shEl tercer script del toolkit copia /srv/veloz/datos y ~/veloz-ops/etc con rsync --link-dest, comprime el histórico con tar, verifica con sha256sum, aplica retención y registra el resultado, cumpliendo las siete propiedades de 07-02:
#!/usr/bin/env bash
# respaldo.sh — Respaldo diario de datos y configuracion de Veloz Envios.
# CUANDO: 03:15 diario | LOG: ~/veloz-ops/logs/respaldo.log
# SI FALLA: 74 = espacio o E/S, 65 = origen ilegible. Relanzar es seguro.
set -euo pipefail
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
export LC_ALL=C; umask 077 # los respaldos no son publicos
readonly BASE="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
. "$BASE/lib/comun.sh"
[[ -r $BASE/etc/veloz-ops.conf ]] && . "$BASE/etc/veloz-ops.conf"
readonly RAIZ="${RESPALDO_RAIZ:-/respaldos/diarios}" RETENER="${RESPALDO_RETENER:-7}"
readonly ORIGENES=(/srv/veloz/datos "$BASE/etc") FECHA=$(date +%F)
SIMULAR=0; EJECUTA=()
copia_incremental() {
local previa destino="$RAIZ/$FECHA" enlace=() origen
previa=$(find "$RAIZ" -mindepth 1 -maxdepth 1 -type d ! -name "$FECHA" -printf '%f\n' |
sort -r | head -1)
[[ -n $previa ]] && enlace=(--link-dest="$RAIZ/$previa")
"${EJECUTA[@]}" mkdir -p "$destino"
for origen in "${ORIGENES[@]}"; do
[[ -r $origen ]] || veloz_morir 65 "no puedo leer $origen"
"${EJECUTA[@]}" rsync -a --delete "${enlace[@]}" \
--exclude-from="$BASE/etc/respaldo.exclude" \
"$origen/" "$destino/$(basename -- "$origen")/"
done
veloz_log_info "copia incremental en $destino (base: ${previa:-ninguna})"
}
archiva_historico() {
local tgz="$RAIZ/$FECHA/historico-$FECHA.tar.gz"
(( SIMULAR )) && { veloz_log_info "[SIMULACION] archivaria el historico"; return 0; }
tar czf "$tgz" -C /srv/veloz/datos historico
tar -tzf "$tgz" > /dev/null || veloz_morir 74 "archivo corrupto: $tgz"
( cd -- "$RAIZ/$FECHA" && sha256sum "${tgz##*/}" > "${tgz##*/}.sha256" )
veloz_log_info "historico archivado y verificado ($(stat -c %s "$tgz") bytes)"
}
# aplica_retencion y comprueba_espacio: los bucles de los apartados 6 y 8,
# con "${EJECUTA[@]}" delante del rm -rf y ${RAIZ:?} como salvaguarda.
main() {
[[ ${1:-} == -n || ${1:-} == --dry-run ]] && { SIMULAR=1; EJECUTA=(echo "[SIMULACION]"); }
veloz_requiere rsync tar sha256sum
exec 9>/var/lock/veloz-respaldo.lock
flock -n 9 || { veloz_log_info "ya en curso"; exit 0; }
veloz_log_info "INICIO respaldo $FECHA (simular=$SIMULAR)"
comprueba_espacio; copia_incremental; archiva_historico; aplica_retencion
veloz_log_info "FIN ok: respaldo $FECHA completado"
}
main "$@"Tres decisiones merecen comentario. umask 077 porque un respaldo con datos de clientes no debe ser legible por todo el mundo. El --link-dest se construye como array (enlace=()) para que, cuando no haya copia previa, la opción desaparezca por completo de la orden en lugar de quedar vacía. Y ${RAIZ:?} en el rm -rf es una salvaguarda esencial: si RAIZ estuviera vacía por un error de configuración, rm -rf "/${copias[i]}" sería catastrófico; con :? el script muere antes.
En el crontab va a las 03:15 —no a las 03:00, para no coincidir con todo lo demás—, envuelto en timeout 3600s y con >> logs/respaldo.log 2>&1. Es una versión funcional, no la definitiva: falta el envío fuera del servidor (07-06), la comprobación de que el respaldo de anoche existe (07-04) y la restauración guiada. El proyecto 09-03 lo lleva a su versión completa, con menú de restauración, informe y pruebas.
Errores Comunes y Consejos
- Respaldar el directorio de respaldos. Duplica el tamaño en cada vuelta hasta llenar el disco. Exclúyelo siempre.
- La barra final de
rsync. Con barra copia el contenido; sin barra crea un nivel de más. Revísala antes de cada--delete. --deletesin retención. Un borrado accidental en el origen destruye también la copia.--link-destentre discos distintos, o editar dentro de un respaldo. Los enlaces duros no cruzan sistemas de ficheros (sin aviso, hace copias completas y llena el disco); y donde sí funcionan, modificar un fichero lo modifica en todas las copias que lo comparten.- Copiar ficheros de base de datos en caliente. Produce una copia inconsistente que falla al restaurar. Usa
mysqldump/pg_dump. - No comprobar el espacio antes, o guardar la clave de cifrado junto al respaldo. Un respaldo truncado por disco lleno parece válido hasta que lo necesitas; y la clave junto al fichero cifrado equivale a no cifrar.
- Restaurar sobre los datos originales para «probar». Si la copia está mal, destruyes también lo que quedaba. A un temporal.
- Consejo: apunta en el calendario una restauración de prueba mensual y trátala como una tarea real. El respaldo que nunca se ha restaurado tiene una probabilidad de funcionar sorprendentemente baja.
Ejercicios
Ejercicio 1. Explica qué hace mal cada una de estas tres órdenes y corrígelas.
rsync -av --delete /srv/veloz/datos /respaldos/actual
tar czf /respaldos/datos.tar.gz /srv/veloz/datos
find /respaldos -mtime +7 -deleteEjercicio 2. Escribe una función veloz_verifica_respaldo que reciba la ruta de un .tar.gz y compruebe tres cosas: que existe y supera un tamaño mínimo, que el archivo se lee entero, y que su suma sha256 coincide con el .sha256 que lo acompaña. Debe devolver códigos distintos para cada fallo.
Soluciones
Solución 1.
# 1. Sin barra final crea /respaldos/actual/datos/; -v genera un log inmanejable en automatico.
rsync -a --delete /srv/veloz/datos/ /respaldos/actual/
# 2. Sin fecha, sobrescribe la copia de ayer: si hoy falla, te quedas sin ninguna.
# Ademas guardaba rutas absolutas dentro del archivo.
tar czf "/respaldos/datos-$(date +%F).tar.gz" -C /srv veloz/datos
# 3. Borra FICHEROS sueltos dentro de los respaldos, no directorios completos,
# y podria vaciar copias validas dejando el esqueleto.
find /respaldos -mindepth 1 -maxdepth 1 -type d -mtime +7 -exec rm -rf {} +El fallo más grave es el segundo: un respaldo sin fecha en el nombre es un respaldo de una sola generación, y el día que el proceso falle a la mitad habrás destruido la copia buena de ayer para dejar una corrupta de hoy.
Solución 2.
# veloz_verifica_respaldo — comprueba tamano, integridad y suma de un .tar.gz.
# Codigos: 0 ok | 66 no existe o vacio | 74 corrupto | 65 la suma no coincide
veloz_verifica_respaldo() {
local archivo="${1:?falta el archivo}" minimo="${2:-1024}" tamano
[[ -f $archivo ]] || { veloz_log_error "no existe: $archivo"; return 66; }
tamano=$(stat -c %s "$archivo")
(( tamano >= minimo )) || { veloz_log_error "$archivo solo tiene $tamano bytes"; return 66; }
tar -tzf "$archivo" > /dev/null 2>&1 || { veloz_log_error "$archivo esta corrupto"; return 74; }
if [[ -f $archivo.sha256 ]]; then
( cd -- "$(dirname -- "$archivo")" && sha256sum -c --status "${archivo##*/}.sha256" ) ||
{ veloz_log_error "la suma de $archivo no coincide"; return 65; }
else
veloz_log_warn "sin fichero .sha256 para $archivo (no verificado)"
fi
veloz_log_info "respaldo verificado: $archivo ($tamano bytes)"
}El sha256sum -c se ejecuta dentro de una subshell con cd porque el fichero .sha256 guarda el nombre relativo; sin ese cambio de directorio, la comprobación buscaría el archivo en el directorio actual y fallaría siempre. --status silencia la salida para que solo hable el código de salida, que es lo que necesita un script. Y la ausencia del .sha256 se registra como aviso pero no invalida el respaldo: no es lo mismo «no verificado» que «verificado y mal».
Conclusión
Un respaldo empieza por decidir qué copiar: datos, configuración y estado, nunca el sistema entero ni el propio directorio de respaldos. La regla 3-2-1 —tres copias, dos medios, una fuera— y las dos preguntas de RPO y RTO fijan la frecuencia y el diseño antes de escribir una línea. De las estrategias, la completa es simple y cara, la incremental barata y frágil al restaurar, la diferencial un punto medio; pero para ficheros la mejor opción es rsync --link-dest, que genera copias como incrementales y las restaura como completas gracias a los enlaces duros —con la condición de estar en el mismo sistema de ficheros y de no editar nunca dentro de un respaldo—. De las herramientas: tar czf con -C, nombre con %F y --exclude-from para congelar árboles; y rsync con -a siempre, -z solo por red, --delete únicamente cuando hay varias copias retenidas y jamás sin un --dry-run previo, cuidando la barra final del origen. Retén con política decreciente (7 diarias, 4 semanales, 6 mensuales) por nombre ordenado o por find -mtime, con la salvaguarda de no borrar si hay menos copias de las esperadas. Verifica en tres niveles —tamaño mínimo, tar -tzf y sha256sum -c—, porque un respaldo no verificado no es un respaldo, y restaura de verdad, a un directorio temporal y nunca sobre el original. Para bases de datos, mysqldump --single-transaction o pg_dump -Fc, porque copiar sus ficheros en caliente da una foto inconsistente; y si la copia sale del servidor, cifrado con gpg y la clave guardada fuera del sistema.
respaldo.sh ya vive en el toolkit y se ejecuta a las 03:15 con candado, comprobación de espacio y retención; el proyecto 09-03 lo llevará a su versión completa. Pero ahora tienes tres tareas automáticas escribiendo en tres logs que crecen sin parar, y una pregunta sin responder: ¿quién se entera si una de ellas deja de funcionar? En 07-04 atacamos las dos caras de ese problema: el registro —diseñar un formato de línea, una función veloz_log con niveles, logger hacia el syslog, journalctl para consultar y logrotate para que los ficheros no se coman el disco— y la monitorización —umbrales, alertas sin ruido, comprobaciones al estilo de los plugins clásicos y avisos que suenan una sola vez—. Nace vigilante.sh.
Curso de Programación en Bash
Módulo 1: Introducción a Bash
- ¿Qué es Bash?
- Configurando tu Entorno
- Navegación Básica en la Línea de Comandos
- Entendiendo el Shell
- Encontrar Ayuda: man, help y --help
Módulo 2: Comandos Básicos de Bash
- Operaciones con Archivos y Directorios
- Comandos de Procesamiento de Texto
- Permisos y Propiedad de Archivos
- Redirección y Tuberías
- Comodines y Expansión de Rutas
- Historial y Atajos de Teclado
Módulo 3: Fundamentos de Scripting
- Creando y Ejecutando un Script
- Variables y Constantes
- Operadores Básicos
- Sentencias Condicionales
- Argumentos y Entrada del Usuario
- Comillas, Expansión y Sustitución
Módulo 4: Scripting Intermedio
- Bucles en Bash
- Funciones en Bash
- Arrays y Arrays Asociativos
- Manipulación de Cadenas
- La Sentencia case y los Menús Interactivos
- Aritmética y Cálculos Numéricos
Módulo 5: Técnicas Avanzadas de Scripting
- Operaciones Avanzadas con Archivos
- Gestión de Procesos
- Manejo de Errores y Depuración
- Expresiones Regulares
- Entrada/Salida Avanzada: Descriptores y Here-Documents
- Scripts Modulares y Librerías Reutilizables
Módulo 6: Trabajando con Herramientas Externas
Módulo 7: Automatización y Programación
- Trabajos Cron
- Automatizando Tareas
- Scripts de Respaldo y Restauración
- Monitoreo y Registro
- Servicios y Temporizadores con systemd
- Automatización Remota con SSH
Módulo 8: Mejores Prácticas y Optimización
- Escribiendo Código Legible
- Optimizando Scripts en Bash
- Consideraciones de Seguridad
- Control de Versiones con Git
- Análisis Estático con ShellCheck y shfmt
- Pruebas Automatizadas con Bats
- Portabilidad: POSIX sh frente a Bashismos
