Files
takana/scripts/cosmic/cosmic-nested.sh
T
Sergio 476168bb07 takana etapa 5c: comentarios de scripts, MOTD, y un BUG que introdujo la etapa 4
250 líneas de comentario en 151 scripts. Control verificado: el diff no toca
NI UNA línea que no empiece por #, y la sintaxis de los 151 pasa.

El barrido saltea heredocs y cadenas triples, y el guardián DISPARÓ 3 veces:
las tres eran el MOTD que el script escribe DENTRO de la imagen construida —
texto del producto, no comentario del script. Se cambiaron aparte y a
propósito, que es rebranding, no limpieza.

Y el hallazgo caro:  casaba contra ,
que es el TARGET de tracing — o sea el module_path!, o sea el nombre del crate.
La etapa 4 lo movió a  y el script quedó casando NADA. No fallaba:
imprimía cero atribuciones, indistinguible de un log sin problemas. Comprobado
con el binario (RUST_LOG=info sobre zlib), no deducido. Ahora acepta las dos, y
tiene que seguir aceptándolas porque los logs viejos en disco dicen la vieja.

Además 14 rutas de módulo  en docs, que el barrido anterior no tocó
porque  no es frontera de palabra.
2026-09-09 19:28:48 +00:00

143 lines
8.8 KiB
Bash
Executable File

#!/bin/sh
# cosmic-nested.sh — arranca `escritorio-cosmic` como una VENTANA del compositor que ya tenés
# delante, sin QEMU y sin imagen de disco. Hermano de `scripts/wlr/sway-nested.sh`; comparte con él
# el porqué (ciclo de segundos en vez de una tanda, y defectos que sólo se ven MIRANDO) y las dos
# capas de overlay, porque ningún perfil de `targets.toml` incluye la libc.
#
# ══ LO QUE COSMIC HACE DISTINTO ════════════════════════════════════════════════════════════════
# · `cosmic-comp` elige backend solo. Con `WAYLAND_DISPLAY` puesto usa winit sobre Wayland; ANTES
# intenta X11 y falla ruidosamente («$DISPLAY variable not set»). Ese ERROR es normal acá y no
# significa que no haya arrancado: lo que manda es si aparece su socket en `$XDG_RUNTIME_DIR`.
# · **`cosmic-session` no sirve para nestear**: no le pasa `WAYLAND_DISPLAY` a `cosmic-comp` —para
# ella el compositor ES el display server—, así que el comp intenta X11 y DRM/udev y muere antes.
# Y su stderr lo captura `launch_pad`, que sólo reporta «cosmic-comp exited with error code 1» y
# lo reinicia en bucle: la CAUSA no aparece en ningún log. Medido, con todo lo demás igual:
# con WAYLAND_DISPLAY → socket /run/user/0/wayland-1, comp vivo hasta el backend
# sin WAYLAND_DISPLAY → comp muerto antes
# Por eso el modo por defecto es `bare`: el compositor a mano y los clientes apuntados a SU socket,
# igual que hace `cosmic-start.sh` sin sesión. `MODE=session` reproduce el fallo, no lo arregla.
#
# ══ ⚠ EL CIERRE DEL PERFIL NO PUEDE HACER GL, Y ESO NO ESTÁ EN `targets.toml` ═══════════════════
# Medido el 2026-09-04: `/usr/lib/dri` del rootfs hidratado trae **`iris_dri.so` y nada más** — el
# driver de Intel REAL. Sin `swrast_dri.so`, EGL no inicializa y cosmic-comp muere con
# `Egl(InitFailed(NotInitialized))` después de dos `MESA-LOADER: failed to open {zink,swrast}`.
#
# No es un descubrimiento nuevo, es un hueco de DECLARACIÓN: `scripts/gnome/qemu-desktop-image.sh`
# ya dice «el rootfs GNOME sólo trae iris_dri, que es Intel real» y copia `mesa-llvmpipe` ENCIMA con
# `--remove-destination`. O sea que cada script de imagen inyecta a mano algo que el perfil no
# declara — la misma divergencia que `hydrate-profile.py` existe para hacer visible.
#
# **Por qué no se arregla declarándolo y ya:** `mesa` y `mesa-llvmpipe` instalan los MISMOS `.so`
# (`libEGL`, `libgbm`, `libGLESv2`), así que declarar las dos en un perfil colisiona fichero a
# fichero — la figura de las dos poppler que dejó a zathura fuera de KDE. Los scripts lo resuelven
# PISANDO, que es una decisión de imagen, no una arista de grafo. Acá se hace lo mismo y se dice:
# `mesa-llvmpipe` entra como TERCER overlay, el último, o sea el de mayor prioridad.
# · **No hay `grim`**: COSMIC no implementa `wlr-screencopy` sino su `zcosmic_screencopy`, así que
# la captura sale por `cosmic-screenshot` (cadena del portal). Si el portal no está, no hay foto
# y hay que mirar la ventana — se dice, no se falsea con una captura del host.
#
# uso: scripts/cosmic/cosmic-nested.sh
# env: RFS (def /mnt/cosecha/escritorios/cosmic-rootfs) hidratado con hydrate-profile.py
# BASE (def .dev-fs/alpine) capa con la libc
# MODE (def session | bare) sesión completa o sólo el compositor
# OUT (def /mnt/cosecha/escritorios) dónde deja la captura
# SECS (def 0 = quedarse abierto)
# MESA (def el artefacto vigente de mesa-llvmpipe) GL por software; "" para no inyectar
set -u
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"; cd "$ROOT"
RFS="${RFS:-/mnt/cosecha/escritorios/cosmic-rootfs}"
BASE="${BASE:-$ROOT/.dev-fs/alpine}"
MODE="${MODE:-bare}"; OUT="${OUT:-/mnt/cosecha/escritorios}"; SECS="${SECS:-0}"
mkdir -p "$OUT"
# GL por software. Se resuelve por HASH VIGENTE (`takana hash`), no por el más reciente del store:
# con dos artefactos del mismo paquete conviviendo, la fecha miente.
if [ -z "${MESA+x}" ]; then
MH=$(./target/release/takana --store ./store hash recipes/mesa-llvmpipe.toml 2>/dev/null | tr -d "\n" | sed "s/b3://")
MESA=$(ls -d store/"$MH"-mesa-llvmpipe 2>/dev/null || true)
[ -n "${MESA:-}" ] || echo " ⚠ sin mesa-llvmpipe sellado: el compositor NO va a poder iniciar EGL" >&2
fi
[ -d "$RFS" ] || { echo "falta el rootfs del perfil: $RFS" >&2
echo " scripts/hydrate-profile.py escritorio-cosmic --store /mnt/cosecha/store --into $RFS" >&2; exit 1; }
[ -d "$BASE" ] || { echo "falta la capa base con la libc: $BASE" >&2; exit 1; }
HOST_XDG="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
HOST_WL="${WAYLAND_DISPLAY:-wayland-0}"
case "$HOST_WL" in /*) SOCK="$HOST_WL" ;; *) SOCK="$HOST_XDG/$HOST_WL" ;; esac
[ -S "$SOCK" ] || { echo "no hay socket Wayland del host en $SOCK" >&2; exit 1; }
echo "== host: $SOCK rootfs: $RFS modo: $MODE"
# El ORDEN importa: el último `--overlay-src` es el de mayor prioridad, así que mesa-llvmpipe pisa
# los `.so` de la mesa iris del cierre — que es exactamente lo que hacen los scripts de imagen.
exec bwrap \
--overlay-src "$BASE" --overlay-src "$RFS" ${MESA:+--overlay-src "$MESA"} --tmp-overlay / \
--dev /dev --proc /proc --tmpfs /tmp --tmpfs /run \
--dev-bind-try /dev/dri /dev/dri \
--ro-bind "$SOCK" /run/wl-host \
--bind "$OUT" /salida \
--unshare-pid --unshare-uts --hostname cosmic-nested \
--uid 0 --gid 0 --die-with-parent \
--setenv PATH /usr/bin:/bin:/usr/sbin:/sbin \
--setenv HOME /root --setenv SHELL /bin/bash --setenv TERM xterm-256color \
--setenv XDG_RUNTIME_DIR /run/user/0 \
--setenv WAYLAND_DISPLAY /run/wl-host \
--setenv XDG_DATA_DIRS /usr/share \
--setenv XDG_CURRENT_DESKTOP COSMIC \
--setenv XDG_SESSION_TYPE wayland \
--setenv RUST_BACKTRACE 1 \
/bin/sh -c '
set -u
mkdir -p /run/user/0 /run/dbus /root/.config /etc; chmod 700 /run/user/0
[ -s /etc/passwd ] || echo "root:x:0:0:root:/root:/bin/sh" > /etc/passwd
[ -s /etc/machine-id ] || tr -d - < /proc/sys/kernel/random/uuid > /etc/machine-id
mkdir -p /dev/shm 2>/dev/null || true
# El bus de SESIÓN: el panel, el osd y las notificaciones hablan por él. En `session` lo abre
# `dbus-run-session`; en `bare` no hay quien lo abra, y sin él los clientes arrancan mudos.
export DBUS_SESSION_BUS_ADDRESS=$(dbus-daemon --session --fork --print-address 2>/dev/null)
echo " dbus=${DBUS_SESSION_BUS_ADDRESS:-VACIO}"
if [ "'"$MODE"'" = session ] && [ -x /usr/bin/start-cosmic ]; then
echo "-- start-cosmic (sesión completa) — ⚠ NO NESTEA, ver la cabecera del script"
/bin/bash /usr/bin/start-cosmic --in-login-shell >/tmp/cosmic.log 2>&1 &
else
echo "-- cosmic-comp nesteado (winit sobre el Wayland del host)…"
cosmic-comp >/tmp/cosmic.log 2>&1 &
fi
CS=$!
i=0
while [ $i -lt 80 ]; do
WD=$(ls /run/user/0/wayland-* 2>/dev/null | grep -v lock | head -1)
[ -n "${WD:-}" ] && break
kill -0 $CS 2>/dev/null || { echo " !! la sesión murió antes del socket:"; tail -25 /tmp/cosmic.log; exit 1; }
i=$((i+1)); sleep 0.5
done
[ -n "${WD:-}" ] || { echo " !! sin socket en 40 s:"; tail -25 /tmp/cosmic.log; exit 1; }
echo " compositor OK ($WD) — ventana en tu pantalla"
export WAYLAND_DISPLAY=$(basename "$WD")
# Los clientes, contra el socket que el compositor eligió. Cada uno con `[ -x ]` porque la cola
# se construye por partes y un arranque perdido cuesta más que una comprobación de más.
if [ "'"$MODE"'" != session ]; then
for c in cosmic-bg cosmic-panel cosmic-osd cosmic-notifications cosmic-app-library cosmic-launcher; do
[ -x "/usr/bin/$c" ] && { "/usr/bin/$c" >"/tmp/$c.log" 2>&1 & sleep 1; }
done
fi
sleep 8
echo "== procesos de la sesión =="
ps -o comm 2>/dev/null | grep -E "cosmic|pop-launcher|xdg-desktop" | sort | uniq -c
# `Initializing X11 Backend failed` es NORMAL acá: cosmic-comp prueba X11 antes de winit. Lo que
# importa es el backend que SÍ entró.
echo "== backend =="; grep -iE "winit|backend" /tmp/cosmic.log | grep -viE "X11|DISPLAY variable" | head -4
if command -v cosmic-screenshot >/dev/null 2>&1; then
cosmic-screenshot --interactive=false --save-dir /salida >/tmp/shot.log 2>&1 \
&& echo "== captura en '"$OUT"'" || { echo "== sin captura (portal):"; tail -2 /tmp/shot.log; }
else
echo "== sin cosmic-screenshot en la imagen — mirá la ventana"
fi
echo "== cosmic.log (cola) =="; tail -6 /tmp/cosmic.log; cp /tmp/cosmic.log /salida/cosmic-nested.log 2>/dev/null
if [ '"$SECS"' -gt 0 ]; then sleep '"$SECS"'; kill $CS 2>/dev/null; else wait $CS; fi
'