#!/bin/sh # vigia-ensamblado.sh — ¿de dónde sale cada herramienta que ARMA una imagen: del store o del host? # # ══ EL PUNTO CIEGO QUE CUBRE (medido el 2026-09-22) ═════════════════════════════════════════════ # Los tres scripts de imagen tomaban sus herramientas del `PATH`, y en las TRES máquinas que tenemos # —este hub, su anfitrión y el worker `dev.gioser.net`— no existe ninguna de # `grub-mkimage grub-bios-setup cpio mformat xorriso`. O sea: **el pipeline de imagen estaba roto en # todas partes y sólo se veía al intentar correrlo**, con un `falta cpio` que se lee como un descuido # de la máquina y no como lo que era: la imagen dependiendo de software que nadie declaró. # # Lo absurdo del caso es que SEIS de las siete son nuestras y están selladas: `util-linux` (sfdisk), # `e2fsprogs` (mke2fs), `libarchive` (bsdcpio), `gzip`, `mtools`, `xorriso`. Todas estáticas musl, y # corren tal cual en el host — comprobado ejecutándolas, no supuesto. # # ⚠ **La séptima es el gestor de arranque, y no se puede resolver retirando la rama BIOS.** Hetzner # Cloud **arranca por BIOS** (medido en gioser: no existe `/sys/firmware/efi`, SDD 28 §3.1), así que # la imagen del servidor de producción es justamente la que necesita GRUB. Para objetivos UEFI la # rama soberana ya existe y no lleva gestor: el bzImage ES el binario EFI (ADR 0018). # # uso: scripts/vigia-ensamblado.sh [--fail] # --fail → exit 1 si alguna herramienta no sale del store (para CI) set -eu cd "$(dirname "$0")/.." . scripts/lib/herramientas-desde-store.sh FALLAR=0; [ "${1:-}" = "--fail" ] && FALLAR=1 sellados=0; host=0; faltan=0 mirar() { # mirar if p=$(herramienta "$1" "$2" "$3" 2>/dev/null); then case "$p" in /store/*|store/*|*/store/*) printf ' ✓ %-12s %-22s %s\n' "${2##*/}" "$1" "sellado"; sellados=$((sellados+1)) ;; *) printf ' ⚠ %-12s %-22s %s\n' "${2##*/}" "$1" "DEL HOST ($p) — sin hash"; host=$((host+1)) ;; esac else printf ' ✗ %-12s %-22s %s\n' "${2##*/}" "$1" "NO ESTÁ: ni sellado ni en el host"; faltan=$((faltan+1)) fi } echo "== herramientas del ensamblado de imágenes (store: $(_herr_store))" mirar util-linux sbin/sfdisk sfdisk "particionar" mirar e2fsprogs sbin/mke2fs mke2fs "las ext4 con -d, sin root" mirar libarchive usr/bin/bsdcpio cpio "el initramfs newc" mirar gzip bin/gzip gzip "comprimir el initramfs" mirar mtools usr/bin/mformat mformat "poblar la ESP FAT sin montar" mirar mtools usr/bin/mcopy mcopy "idem" mirar xorriso usr/bin/xorriso xorriso "el ISO" mirar dosfstools sbin/mkfs.vfat mkfs.vfat "vfat, cuando hace falta" echo echo "== el gestor de arranque, que es el hueco de verdad" if [ -f recipes/grub.toml ]; then echo " (hay recipes/grub.toml: actualizá este vigía)" else printf ' ✗ %-12s %-22s %s\n' "grub" "(no hay receta)" "sólo del host" for t in grub-mkimage grub-bios-setup; do if command -v "$t" >/dev/null 2>&1; then printf ' ⚠ %-18s %s DEL HOST, sin hash\n' "$t" "$(command -v "$t")"; host=$((host+1)) else printf ' ✗ %-18s AUSENTE ⇒ la rama BIOS (install-image.sh, iso-image.sh) NO puede correr acá\n' "$t" faltan=$((faltan+1)) fi done echo " Hetzner Cloud arranca por BIOS (medido, SDD 28 §3.1) ⇒ la rama no se puede retirar." echo " Las dos salidas, ninguna gratis: receta de \`grub\`, o receta de \`limine\` (cubre BIOS" echo " y UEFI de una). Para un objetivo UEFI la rama soberana ya está: install-image-efi.sh." fi echo echo "== resumen: $sellados sellada(s) · $host del host (sin hash) · $faltan ausente(s)" [ "$faltan" -gt 0 ] && echo " Una imagen que necesita algo ausente NO se puede armar en esta máquina." if [ "$FALLAR" = 1 ] && { [ "$faltan" -gt 0 ] || [ "$host" -gt 0 ]; }; then exit 1 fi exit 0