2 Commits
+38 -22
View File
@@ -8,12 +8,13 @@
# del lab-agent ya esta configurado) -- nunca se intenta "arreglar"
# la red del host desde aca, eso puede ser un problema de
# hardware/BIOS fuera del alcance del contenedor.
# b) Existencia de la sesion tmux "lab". Si no existe (crash, o el
# contenedor se acaba de recrear), SI se recrea automaticamente --
# es solo recuperar el propio entorno de trabajo, no tocar
# infraestructura externa. Al recrearla tambien se lanza `claude`
# adentro (ver launch_claude_in_session) -- una sesion recreada sin
# esto es un shell pelado, no "el entorno de trabajo".
# b) Existencia de cada sesion tmux en SESSIONS (ver mas abajo -- hoy
# "lab" y "cloud-practice"). Si no existe (crash, o el contenedor
# se acaba de recrear), SI se recrea automaticamente -- es solo
# recuperar el propio entorno de trabajo, no tocar infraestructura
# externa. Al recrearla tambien se lanza `claude` adentro (ver
# launch_claude_in_session) -- una sesion recreada sin esto es un
# shell pelado, no "el entorno de trabajo".
#
# Todo evento (chequeo ok, falla, accion tomada) queda en LOG_FILE, que
# vive bajo /DATA (persistente, sobrevive a recrear el contenedor) y no
@@ -24,7 +25,15 @@
set -uo pipefail
WORKDIR="/DATA/AppData/k3d-lab-v3/lab-cruzcloud"
SESSION="lab"
# Cada entrada: "nombre-sesion:workdir". "cloud-practice" agregada
# 2026-09-20 (ver ADR 0012, practica multi-cloud) -- vive en un
# subdirectorio de WORKDIR (repo platform-multicloud ya clonado ahi),
# asi que el mismo wait_for_workdir() de abajo (que solo espera por el
# WORKDIR padre) ya cubre el caso de arranque en frio para las dos.
SESSIONS=(
"lab:${WORKDIR}"
"cloud-practice:${WORKDIR}/platform-multicloud"
)
LOG_DIR="/DATA/AppData/k3d-lab-v3/tmux-host/logs"
LOG_FILE="${LOG_DIR}/health.log"
# Reusa el mismo canal de Telegram que ya configuro scripts/lab-agent/ --
@@ -105,6 +114,7 @@ check_network() {
}
launch_claude_in_session() {
local session="$1"
# El pane recien creado tarda un instante en tener su shell listo para
# recibir input -- un send-keys inmediato a veces se pierde. 1s alcanza
# sobrado para un shell interactivo local (no depende de red).
@@ -113,47 +123,53 @@ launch_claude_in_session() {
# controlable remotamente en claude.ai (confirmado en vivo 2026-09-20 --
# sin la flag, "remoteEnabled" queda en false para siempre porque nadie
# la pide). El nombre de sesion remota usa el hostname del contenedor
# (ZimaOS) como prefijo por defecto.
# (ZimaOS) como prefijo por defecto -- con 2 sesiones corriendo
# "claude --remote-control" a la vez, cada una aparece como una sesion
# remota distinta en claude.ai (mismo prefijo de host, pero cada una
# con su propio ID de sesion real).
# --continue (-c): retoma la conversacion mas reciente en WORKDIR en vez
# de arrancar una sesion en blanco cada vez que se recrea el pane (reinicio
# del NAS, crash del contenedor, etc). Si no hay conversacion previa en el
# directorio, el propio CLI arranca una nueva sin error.
if tmux send-keys -t "$SESSION" "claude --remote-control --continue" Enter 2>>"$LOG_FILE"; then
log "TMUX: 'claude --remote-control --continue' lanzado dentro de la sesion recien creada"
if tmux send-keys -t "$session" "claude --remote-control --continue" Enter 2>>"$LOG_FILE"; then
log "TMUX: 'claude --remote-control --continue' lanzado dentro de la sesion '${session}' recien creada"
else
log "TMUX: ERROR al lanzar 'claude --remote-control --continue' dentro de la sesion recien creada"
log "TMUX: ERROR al lanzar 'claude --remote-control --continue' dentro de la sesion '${session}' recien creada"
fi
}
check_tmux_session() {
if tmux has-session -t "$SESSION" 2>/dev/null; then
log "TMUX: sesion '${SESSION}' ok"
local session="$1" workdir="$2"
if tmux has-session -t "$session" 2>/dev/null; then
log "TMUX: sesion '${session}' ok"
return
fi
if [[ ! -d "$WORKDIR" ]]; then
# No se crea sobre un WORKDIR ausente (quedaria posicionada en /). Se
if [[ ! -d "$workdir" ]]; then
# No se crea sobre un workdir ausente (quedaria posicionada en /). Se
# reintenta en el proximo ciclo -- ver STARTUP_MOUNT_WAIT_MAX_SEC arriba
# para el caso especifico de arranque en frio del host.
log "TMUX: sesion '${SESSION}' no existe y ${WORKDIR} tampoco -- no se crea esta vuelta, se reintenta en el proximo ciclo (${INTERVAL_SEC}s)."
log "TMUX: sesion '${session}' no existe y ${workdir} tampoco -- no se crea esta vuelta, se reintenta en el proximo ciclo (${INTERVAL_SEC}s)."
return
fi
log "TMUX: sesion '${SESSION}' no existe -- recreando en ${WORKDIR}"
if tmux new-session -d -s "$SESSION" -c "$WORKDIR" 2>>"$LOG_FILE"; then
log "TMUX: sesion '${SESSION}' recreada exitosamente"
log "TMUX: sesion '${session}' no existe -- recreando en ${workdir}"
if tmux new-session -d -s "$session" -c "$workdir" 2>>"$LOG_FILE"; then
log "TMUX: sesion '${session}' recreada exitosamente"
# Una sesion recreada sin esto es un shell vacio hasta que alguien
# entre a mano y escriba "claude" -- exactamente el gotcha reportado
# tras el reinicio completo del NAS del 2026-09-18/19: la sesion SI se
# recreaba sola (confirmado en el log de ese arranque), pero Claude
# Code nunca arrancaba adentro.
launch_claude_in_session
launch_claude_in_session "$session"
else
log "TMUX: ERROR al recrear la sesion '${SESSION}'"
log "TMUX: ERROR al recrear la sesion '${session}'"
fi
}
log "=== healthcheck inicio (intervalo=${INTERVAL_SEC}s) ==="
while true; do
check_network
check_tmux_session
for entry in "${SESSIONS[@]}"; do
check_tmux_session "${entry%%:*}" "${entry#*:}"
done
sleep "$INTERVAL_SEC"
done