Verificar las descargas antes de sustituir archivos

ShellBeginner
Practicar Ahora

Introducción

Field Notes ya sabe qué recursos están dañados o ausentes. Ahora necesita una rutina de reparación: obtener solo esos recursos, comparar sus bytes con una referencia independiente y publicar cada sustitución únicamente después de validarla. El origen puede devolver un error HTTP o una respuesta HTTP perfectamente satisfactoria que contenga el documento equivocado.

Este laboratorio empieza con su propio paquete preparado. Necesitas los conocimientos del laboratorio anterior sobre SHA256, lectura de líneas completas, sustitución de comandos y nombres completos; no necesitas archivos de la VM anterior. Workspace y Download Desk comparten un contenedor. El PDF sintético original y curl ya están preparados. El tiempo es una estimación del autor que incluye lectura y recuperación de errores.

Descargar un candidato antes de sustituir archivos

En este paso, guardarás y verificarás un documento real en un directorio de práctica separado.

Empieza en Workspace, preparado para texto UTF-8. Utiliza esta ruta absoluta cuando no encuentres un nombre relativo. pwd y ls pack ayudan a distinguir un directorio incorrecto de un nombre mal escrito.

cd /home/labex/project/download-desk

El manifiesto de confianza es /opt/labex/download-pack-state/expected.sha256. Su formato es el del primer laboratorio: 64 caracteres hexadecimales en minúsculas, dos espacios y un nombre completo de un solo nivel. Se proporciona de forma independiente, es legible, no está vacío y termina en un salto de línea. Los nombres utilizan ASCII imprimible y pueden contener espacios; las barras, las barras inversas, CR, LF, los tabuladores y los nombres . y .. quedan fuera del alcance. Utiliza directorios reales sin padres enlazados. Un miembro esperado debe estar ausente o ser un archivo local regular; se rechazan los enlaces y los objetos de directorio. No modifiques la referencia ni el origen. Una coincidencia SHA256 demuestra concordancia con esta referencia de confianza, no la identidad de quien publica el archivo.

cat /opt/labex/download-pack-state/expected.sha256

El directorio preparado trial sirve para experimentar y está separado del pack del organizador. mktemp crea un archivo vacío único a partir de una plantilla que termina en caracteres X e imprime su ruta. Capturarla en candidate permite seguir usándola en esta sesión de Workspace. Una conexión nueva puede perder las variables de shell; en ese caso, empieza de nuevo esta secuencia de práctica en lugar de adivinar el valor anterior.

candidate=$(mktemp trial/.incoming.XXXXXX)

curl realiza una petición HTTP. Estas opciones tienen funciones distintas:

  • --get envía una petición GET y --data-urlencode 'name=Workshop card.txt' codifica el nombre de forma segura como parámetro de consulta. Las comillas protegen los argumentos de shell; la codificación URL trata los espacios dentro de la petición.
  • --fail hace que los errores HTTP, como 503, produzcan un estado de salida no nulo. No detecta un cuerpo incorrecto devuelto con HTTP 200.
  • --silent --show-error oculta el progreso y conserva los mensajes de error. --max-time 8 limita toda la transferencia a ocho segundos.
  • --output "$candidate" escribe únicamente en el candidato temporal. 127.0.0.1:8080 es el origen local preparado en este mismo contenedor; /good sirve los bytes correctos.
curl --fail --silent --show-error --get --data-urlencode 'name=Workshop card.txt' --max-time 8 --output "$candidate" http://127.0.0.1:8080/good
printf 'Download exit: %s\n' "$?"

Debes ver Download exit: 0. Si escribiste mal la URL, curl puede informar de un fallo de conexión o de un rechazo HTTP. Corrige la dirección anterior, elimina solo tu candidato actual con rm -- "$candidate" y repite desde mktemp. -- termina las opciones y esta variable exacta identifica tu propio experimento.

Copia el resumen esperado del documento desde su línea en el manifiesto de confianza. Es el valor siguiente, independiente del candidato:

expected=a9986fb03d5ca72e42753d0ddd11dce7794b0e5a8b253dd4cd356825ca6d0583

Una tubería, |, conecta la salida estándar de un comando con la entrada estándar del siguiente. Este printf construye un registro de suma que apunta a tu candidato. sha256sum --check lee ese registro y && ejecuta mv solo si la comprobación tiene éxito. mv -- cambia el nombre del candidato verificado al nombre final de práctica. Puedes sustituir este archivo al repetir el experimento; las reglas de reparación selectiva del organizador se aplican a pack.

printf '%s  %s\n' "$expected" "$candidate" | sha256sum --check && mv -- "$candidate" "trial/Workshop card.txt"

Debes obtener una línea que termine en : OK. Si indica FAILED, no muevas el candidato: elimina solo ese archivo y repite la descarga corregida. Ya puedes leer el documento verificado:

cat "trial/Workshop card.txt"
REPAIR DESK: EAST HALL

Has mantenido una descarga sin verificar alejada de un nombre final. A continuación aplicarás este orden al paquete completo.

Reparar selectivamente y recuperarse de los fallos

En este paso, darás tres argumentos a la rutina y probarás tanto su resultado útil como su límite de protección ante fallos.

Empieza en Workspace, en /home/labex/project/download-desk. El contrato del script es bash repair-pack.sh MANIFEST SOURCE_URL PACK_DIRECTORY. Es un programa Bash autónomo que usa esos argumentos y los comandos instalados, sin archivos auxiliares vecinos. Primero debe clasificar los bytes reales de cada miembro. Un miembro coincidente no genera peticiones de descarga y conserva sus bytes, modo, propietario y mtime. El archivo ajeno a la tarea pack/notes.txt tiene la misma protección. Solo pueden descargarse miembros ausentes o no coincidentes, como máximo una vez cada uno por ejecución. Un archivo vacío coincidente es correcto. Con el paquete completo, una segunda ejecución debe generar cero peticiones de descarga y conservar todo su estado.

Cada candidato se guarda junto a su destino y se elimina tras el éxito normal o un fallo comunicado. La publicación es por archivo: una sustitución verificada puede permanecer si falla un miembro posterior. Los candidatos fallidos o incorrectos nunca sustituyen su destino. Esto no es una transacción del paquete entero ni una garantía frente a escritores simultáneos, cortes de energía o cualquier condición de terminación del proceso. Utiliza solo las rutas del curso, sin ediciones concurrentes.

El analizador y la extracción del resumen utilizan la sintaxis del laboratorio anterior. Estos elementos adicionales protegen el límite de sustitución:

  • [ -r "$manifest" ] comprueba la lectura; [ -s "$manifest" ] exige un manifiesto no vacío. ! niega una prueba. || significa OR entre pruebas o ejecuta una rama de fallo cuando falla el comando anterior. Aquí && significa AND. Las llaves agrupan pruebas relacionadas sin crear una subshell.
  • [ -d "$pack" ] comprueba un directorio. [ -L "$target" ] detecta incluso enlaces rotos; -e comprueba un destino existente y -f un archivo regular. Rechazar enlaces y otros tipos antes de mv evita seguir un enlace al origen o mover accidentalmente el candidato dentro de un directorio.
  • temporary= inicia una variable vacía. trap '...' EXIT registra la limpieza al salir del script. Las comillas simples retrasan la expansión hasta ese momento. -n significa que la variable no está vacía; la limpieza elimina solo el archivo creado por el propio script. rm -f acepta silenciosamente que un candidato ya no exista; -- termina las opciones.
  • continue avanza a la siguiente línea del manifiesto. exit 1 comunica un fallo. >&2 envía una explicación al error estándar en lugar de a la salida normal. Vaciar temporary después de renombrar correctamente impide que la limpieza toque un archivo publicado.

Guarda este script completo con el método de here-document literal del primer laboratorio:

cat > repair-pack.sh <<'BASH'
#!/usr/bin/env bash
manifest=$1
base=$2
pack=$3
if [ ! -r "$manifest" ] || [ ! -s "$manifest" ]; then
    printf 'A readable nonempty trusted manifest is required.\n' >&2
    exit 1
fi
if [ ! -d "$pack" ] || [ -L "$pack" ]; then
    printf 'A real pack directory is required.\n' >&2
    exit 1
fi
temporary=
trap 'if [ -n "$temporary" ]; then rm -f -- "$temporary"; fi' EXIT
while IFS= read -r line; do
    expected=${line:0:64}
    name=${line:66}
    target=$pack/$name
    if [ -L "$target" ] || { [ -e "$target" ] && [ ! -f "$target" ]; }; then
        printf 'Expected a regular file or absent member: %s\n' "$name" >&2
        exit 1
    fi
    if [ -f "$target" ]; then
        actual=$(sha256sum -- "$target")
        actual=${actual%% *}
        if [ "$actual" = "$expected" ]; then
            printf 'Keep: %s\n' "$name"
            continue
        fi
    fi
    temporary=$(mktemp "$pack/.repair.XXXXXX") || exit 1
    if ! curl --fail --silent --show-error --get --data-urlencode "name=$name" --max-time 8 --output "$temporary" "$base"; then
        printf 'Download failed: %s\n' "$name" >&2
        exit 1
    fi
    actual=$(sha256sum -- "$temporary")
    actual=${actual%% *}
    if [ "$actual" != "$expected" ]; then
        printf 'Checksum mismatch: %s\n' "$name" >&2
        exit 1
    fi
    mv -- "$temporary" "$target" || exit 1
    temporary=
    printf 'Repaired: %s\n' "$name"
done < "$manifest"
BASH

La limpieza recibe solo tu ruta temporal exacta; no elimina archivos de otras personas. El contrato también permite otro nombre temporal seguro o un bucle equivalente. La comprobación evalúa el comportamiento, no esta escritura exacta de los comandos ni el texto de salida Keep:.

Probar una respuesta HTTP satisfactoria con el cuerpo equivocado

El endpoint controlado /html devuelve una página de error HTML con HTTP 200. Es una respuesta real, no un estado de curl simulado. El siguiente comando debe fallar, sin sustituir el documento dañado existente:

bash repair-pack.sh /opt/labex/download-pack-state/expected.sha256 http://127.0.0.1:8080/html pack
printf 'Repair exit: %s\n' "$?"

Debes ver Repair exit: 1 y Checksum mismatch: Workshop card.txt. El PDF ya era correcto y se omitió. El candidato equivocado se eliminó; el éxito HTTP por sí solo no autorizó su publicación. ls -a incluye nombres ocultos, así que puedes comprobar que no queda ningún candidato .repair.*:

ls -a pack

Ahora utiliza el origen correcto. El script repara el documento y el mapa ausente y conserva el PDF, el archivo vacío de agradecimientos y la nota personal:

bash repair-pack.sh /opt/labex/download-pack-state/expected.sha256 http://127.0.0.1:8080/good pack
(cd pack && sha256sum --check /opt/labex/download-pack-state/expected.sha256)

Todos los miembros enumerados deben indicar OK. Cambia a Download Desk, recarga la página y abre el PDF y el mapa. El mapa indica la entrada este. Selecciona Download junto al PDF y abre el archivo guardado en el lector del navegador. Ambas operaciones consumen tu paquete local; no recuperan contenido del origen como alternativa. Utiliza los controles nativos de zoom para las páginas fijas del PDF. Vuelve a Workspace.

Repetir sin volver a descargar

El origen preparado escribe una línea por cada petición real de recursos en requests.jsonl, incluida la identidad del proceso de origen. Cada evento se vuelca antes de observarlo. wc -l < FILE cuenta líneas redirigiendo el archivo al comando; no solicita ningún recurso. Lee el contador, ejecuta de nuevo la rutina y vuelve a leerlo:

wc -l < /opt/labex/download-pack-state/requests.jsonl
bash repair-pack.sh /opt/labex/download-pack-state/expected.sha256 http://127.0.0.1:8080/good pack
wc -l < /opt/labex/download-pack-state/requests.jsonl

Ambos números deben coincidir. Los cuatro miembros deben conservarse. Volver a descargarlo todo desperdiciaría peticiones y podría cambiar los modos o las marcas de tiempo de archivos correctos, aunque coincidieran los resúmenes finales.

Practicar fallos de transporte fuera del paquete terminado

mkdir -p crea un directorio de experimentación si hace falta. No lo reinicia. Mantén intacto el paquete terminado del organizador:

mkdir -p trial/fault-test

El endpoint controlado /error devuelve HTTP 503. Debes obtener un error de curl que mencione 503 y un estado del script no nulo:

bash repair-pack.sh /opt/labex/download-pack-state/expected.sha256 http://127.0.0.1:8080/error trial/fault-test
printf 'HTTP-error exit: %s\n' "$?"

Debes ver HTTP-error exit: 1. El endpoint controlado /partial cierra la conexión después de enviar solo parte del cuerpo declarado. Debes obtener el error 18 de curl sobre bytes pendientes y, de nuevo, ningún candidato publicado:

bash repair-pack.sh /opt/labex/download-pack-state/expected.sha256 http://127.0.0.1:8080/partial trial/fault-test
printf 'Partial-transfer exit: %s\n' "$?"

Debes ver Partial-transfer exit: 1. Un fallo de conexión, un rechazo HTTP y un cuerpo incorrecto con HTTP 200 son observaciones distintas; todas impiden una sustitución sin verificar. Recupera el experimento con el mismo endpoint correcto y los mismos argumentos:

bash repair-pack.sh /opt/labex/download-pack-state/expected.sha256 http://127.0.0.1:8080/good trial/fault-test

Si escribes mal la ruta del manifiesto o del directorio, el script indica el objeto necesario y termina con estado no nulo. Comprueba pwd, ls y la ruta absoluta de referencia antes de reintentarlo. Si el script guardado tiene un error de sintaxis, sustituye solo repair-pack.sh con el here-document completo anterior. No elimines el paquete del organizador para corregir un error de escritura.

La comprobación final lee tu paquete real y los objetos que deben conservarse. También ejecuta tu script sin modificar en paquetes aislados con otros nombres y fallos HTTP controlados, incluido un destino dañado existente y un miembro vacío legítimo que falta. Esas peticiones proceden de tu script, no de una descarga del evaluador que complete pruebas ausentes. Repetir la comprobación no repara ni reinicia tu trabajo real.

Resumen

Has descargado un candidato, comprobado su SHA256 antes de publicarlo y creado un script reutilizable de reparación selectiva. Los errores HTTP reales, las respuestas satisfactorias con contenido incorrecto y los cuerpos interrumpidos no llegaron a los nombres finales. Los archivos correctos y las notas personales se conservaron, y una segunda ejecución con el paquete completo no necesitó descargas.