restic restore con --include, --exclude y --verify: qué restaura, qué comprueba y qué pasa con un pack corrupto
--include '*.txt' restauró solo los 3 .txt de 5 ficheros (exit 0); --verify sobre repositorio sano verificó 4 ficheros (exit 0); con un pack corrupto, restore falló igual con y sin --verify (exit 1, 9 de 10 elementos) y restic check sin --read-data dijo "no errors were found" (exit 0).
Contenido
Este artículo no contiene enlaces de afiliado.
Restaurar un snapshot entero rara vez es lo que hace falta. Normalmente es una carpeta o un tipo de fichero. restic restore admite --include y --exclude para eso, y --verify para releer lo escrito. Se probó qué hace cada uno y qué ocurre cuando un fichero de datos del repositorio está dañado. Para restaurar un único fichero hay otra guía: restaurar un fichero concreto.
Condiciones: restic 0.16.4 en Linux arm64, repositorio local, 5 ficheros aleatorios de 1 MiB (3 .txt y un .png en docs/, un .log en logs/), contraseña desechable. No se probó con repositorios remotos, ni con snapshots grandes, ni con corrupción en ficheros de índice o de árbol. Script completo al final.
Restaurar solo una parte
| Orden | Ficheros restaurados | Exit |
|---|---|---|
restore latest --include '*.txt' |
f1.txt, f2.txt, f3.txt |
0 |
restore latest --exclude '*.log' --exclude '*.png' |
f1.txt, f2.txt, f3.txt |
0 |
restore latest --include <ruta>/docs --verify |
los 4 ficheros de docs/ |
0 |
Con los patrones, en la carpeta destino solo aparecieron los ficheros esperados (se listó con find). Ojo: restic restaura con la ruta completa original dentro del destino (<destino>/tmp/rrv/data/docs/...), no solo el nombre del fichero.
Qué añade --verify
Con --verify, restic vuelve a leer del disco los ficheros restaurados y los compara con el snapshot. En el repositorio sano la salida añadió dos líneas:
verifying files in /tmp/rrv/r3
finished verifying 4 files in /tmp/rrv/r3 (took 5ms)
El resumen decía "Restored 8 / 5 files/dirs" y, con --verify, el exit fue 0. El mensaje indica cuántos ficheros se comprobaron.
Con un pack corrupto
Se sobrescribieron 64 bytes en mitad del fichero de datos grande del repositorio (había 2 ficheros en data/; se comprobó con sha256sum que cambió). Resultado:
| Orden | Resultado | Exit |
|---|---|---|
restore latest |
"ciphertext verification failed" en f3.txt; "Restored 9 / 10 files/dirs"; "Fatal: There were 2 errors" |
1 |
restore latest --verify |
idéntico; no aparece la línea "verifying files" | 1 |
restore latest --include '*.log' --verify |
restaura el .log y verifica 1 fichero |
0 |
restic check |
"no errors were found" | 0 |
restic check --read-data |
"Fatal: repository contains errors" | 1 |
Lo que se ve: la corrupción la detecta el propio restore (el descifrado falla), con o sin --verify. En esta prueba --verify no cambió nada: con errores ni siquiera llegó a ejecutarse la verificación. El fichero dañado (f3.txt) no quedó en el destino; los demás sí. Restaurar solo el .log funcionó porque ese fichero no estaba en la parte dañada, pero eso depende de dónde caiga el daño, no es una garantía.
Otro dato: restic check sin --read-data dijo que todo iba bien con el pack dañado. Solo --read-data lo encontró. Más sobre esto en restic check y la corrupción.
Qué no se probó
- Corrupción dentro del destino tras restaurar (que es lo que
--verifydebería detectar): no se simuló. - Daño en índices, árboles o
config. - Patrones con
--iinclude, rutas con espacios o--includecombinado con--exclude. - Qué pasa con repositorios remotos o con mucho volumen.
Script completo
#!/bin/bash
# restic restore --include/--exclude/--verify, with and without a corrupted pack.
# Usage: test-restic-restore-verify.sh WORKDIR
W=$1; rm -rf "$W"; mkdir -p "$W/data/docs" "$W/data/logs"
export RESTIC_PASSWORD=prueba-desechable
R="$W/repo"; restic version; restic init -r "$R" >/dev/null
for i in 1 2 3; do head -c 1M /dev/urandom > "$W/data/docs/f$i.txt"; done
head -c 1M /dev/urandom > "$W/data/docs/img.png"
head -c 1M /dev/urandom > "$W/data/logs/app.log"
restic -r "$R" backup "$W/data" --quiet; echo "backup exit=$?"
lst() { (cd "$1" && find . -type f | sort | tr '\n' ' '); echo; }
echo "== 1) --include '*.txt'"
restic -r "$R" restore latest --target "$W/r1" --include '*.txt' >/dev/null; echo "exit=$?"; lst "$W/r1"
echo "== 2) --exclude '*.log' --exclude '*.png'"
restic -r "$R" restore latest --target "$W/r2" --exclude '*.log' --exclude '*.png' >/dev/null; echo "exit=$?"; lst "$W/r2"
echo "== 3) --include docs path + --verify (healthy repo)"
restic -r "$R" restore latest --target "$W/r3" --include "$W/data/docs" --verify 2>&1 | tail -4; echo "exit=${PIPESTATUS[0]}"; lst "$W/r3"
echo "== 4) corrupt one data file (64 bytes overwritten in the middle)"
F=$(find "$R/data" -type f -size +100k | head -1); echo "data files: $(find "$R/data" -type f | wc -l)"
S=$(stat -c %s "$F"); B=$(sha256sum < "$F"); chmod u+w "$F" # repo files are read-only
head -c 64 /dev/urandom | dd of="$F" bs=1 seek=$((S/2)) conv=notrunc 2>/dev/null
[ "$B" = "$(sha256sum < "$F")" ] && echo "WARNING: file unchanged" || echo "pack file modified"
echo "== 5) restore without --verify"
restic -r "$R" restore latest --target "$W/r5" 2>&1 | tail -6; echo "exit=${PIPESTATUS[0]}"
echo "== 6) restore with --verify"
restic -r "$R" restore latest --target "$W/r6" --verify 2>&1 | tail -6; echo "exit=${PIPESTATUS[0]}"
echo "== 7) restore --include '*.log' with --verify"
restic -r "$R" restore latest --target "$W/r7" --include '*.log' --verify 2>&1 | tail -4; echo "exit=${PIPESTATUS[0]}"
echo "== 8) check (metadata only)"; restic -r "$R" check 2>&1 | tail -2; echo "exit=${PIPESTATUS[0]}"
echo "== 9) check --read-data"; restic -r "$R" check --read-data 2>&1 | grep -iE "error|fatal|verif" | head -3; echo "exit=${PIPESTATUS[0]}"