tawasuyu

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

TOML 1572Shell 203Rust 109Markdown 993728 Sutichaykuna

⎇ 476168bb077db780e49c83e3ca4f0d3d230bd58a scripts/farm/tandas.sh Shell · 53 siq'ikuna · 2.4 KB Ñawpa willay ch'uya

takana etapa 5c: comentarios de scripts, MOTD, y un BUG que introdujo la etapa 4 476168bb0 · Sergio ·

1#!/bin/sh
2# tandas.sh — encadena varias campañas de deuda en el worker, en ORDEN y sin solaparse.
3#
4# POR QUÉ EN SERIE Y NO EN PARALELO: dos `takana build` simultáneos sobre el mismo store compiten
5# por el mismo `work/sources` y por el watchdog de disco del worker-loop (que borra árboles que
6# ningún bwrap tiene montado). El paralelismo del worker está DENTRO de cada build (`-j$(nproc)`),
7# no entre builds.
8#
9# POR QUÉ TANDAS Y NO UNA LISTA LARGA: una tanda es una unidad con sentido topológico — la cadena
10# GUI, el stack wayland, los kernels. Si una tanda se cae entera por su raíz (como pango arrastró a
11# 7 recetas el 2026-07-21), se ve de un vistazo en el resumen y se re-lanza sola. Una lista de 40
12# nombres planos no dice nada cuando falla.
13#
14# Espera a que termine cualquier campaña en vuelo antes de arrancar, así se puede encolar mientras
15# otra muele.
16#
17# Uso (en el worker):
18#   scripts/farm/tandas.sh "gui:pixman,cairo,pango" "kernels:linux,linux-generic"
19# Desde el hub:
20#   ssh root@<ip> 'systemd-run --unit=tandas --working-directory=/opt/hammer \
21#                    /opt/hammer/scripts/farm/tandas.sh "gui:pixman,cairo" …'
22#   ssh root@<ip> 'tail -f /var/log/tandas.log'
23set -u
24HAMMER_DIR="${TAKANA_DIR:-${HAMMER_DIR:-/opt/hammer}}"
25cd "$HAMMER_DIR"
26LOG="${LOG:-/var/log/tandas.log}"
27ESPERA="${ESPERA:-30}"
28
29ts() { date -u +%FT%TZ; }
30[ $# -gt 0 ] || { echo "uso: tandas.sh <nombre:receta1,receta2,…> […]" >&2; exit 2; }
31
32# No solaparse con una campaña previa (ni con otra corrida de este mismo script).
33while pgrep -f 'campana-deuda\.s[h]' >/dev/null 2>&1; do
34  echo "$(ts) esperando a que termine la campaña en vuelo…" | tee -a "$LOG"
35  sleep "$ESPERA"
36done
37
38echo "$(ts) ═══ tandas arranca: $# tanda(s)" | tee -a "$LOG"
39resumen=""
40for spec in "$@"; do
41  nombre="${spec%%:*}"
42  lista="$(echo "${spec#*:}" | tr ',' ' ')"
43  n=$(echo "$lista" | wc -w)
44  echo "$(ts) ── TANDA '$nombre' ($n recetas)" | tee -a "$LOG"
45  # campana-deuda.sh ya trae el PATH del go del store, el heartbeat del dead-man y el log por receta.
46  LOG="/var/log/tanda-$nombre.log" scripts/farm/campana-deuda.sh $lista 2>&1 | tee -a "$LOG"
47  ok=$(grep -c '✓ ' "/var/log/tanda-$nombre.log" 2>/dev/null || echo 0)
48  ko=$(grep -c '✗ ' "/var/log/tanda-$nombre.log" 2>/dev/null || echo 0)
49  resumen="$resumen\n   $nombre: $ok selladas, $ko fallidas (de $n)"
50done
51
52echo "$(ts) ═══ tandas fin" | tee -a "$LOG"
53printf "%b\n" "$resumen" | tee -a "$LOG"