gioser

tawasuyu/brahman

Rust 496TOML 195Markdown 55JSON 197001 Definitions

fix(init): la salida de arje-zero ahora se ve en VGA Y serial

Síntoma: el screenshot del usuario en la VPS Hetzner mostraba systemd
booteando y se quedaba congelado en el último printk del kernel justo
antes del switch-root. arje-zero arrancaba bien pero su salida iba al
serial invisible.

Causa: el cmdline traía `console=tty1 console=ttyS0,115200` — y el
kernel hace que `/dev/console` apunte al ÚLTIMO `console=`, así toda la
salida de stdout/stderr de arje-zero (tracing + banner de la rescue
shell) caía en ttyS0 (serial), no en la VGA que muestra noVNC.

Dos arreglos:

- Orden de consolas invertido en el menuentry → `/dev/console` = tty1
  (lo que efectivamente se ve en la consola web del proveedor).
- arje-zero también escribe a `/dev/kmsg` (ring buffer del kernel), que
  el kernel hace eco a TODAS las consolas registradas — el mecanismo
  que usa systemd para que sus mensajes salgan tanto en VGA como en
  serial. Defense in depth: el banner de rescue y un eco temprano
  «despierta como PID 1» aparecen sí o sí en cualquier consola.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

c715ee2dee341c730cd2206797b8bec989f7ac5c · by sergio · (5 months ago) · parent 89fd927f7 · browse the tree at this commit

Semantic delta · 3

crates/init/arje-zero/src/main.rs

2 files · +28 −2

diff --git a/crates/init/arje-zero/src/main.rs b/crates/init/arje-zero/src/main.rs
index 18c3d3e..46977ea 100644
--- a/crates/init/arje-zero/src/main.rs
+++ b/crates/init/arje-zero/src/main.rs
@@ -87,6 +87,10 @@ fn main() -> anyhow::Result<()> {
     }
 
     info!("ente-zero despierta como PID 1");
+    // Eco temprano al ring buffer del kernel: garantiza que el «estoy
+    // vivo» aparezca en TODAS las consolas (VGA + serial), no sólo en
+    // el `/dev/console` apuntado por el último `console=` del cmdline.
+    write_to_kmsg("despierta como PID 1");
     // Doctrina dura: PID 1 NUNCA puede salir — el kernel haría panic
     // ("Attempted to kill init") y, con `panic=N` en el cmdline, la
     // máquina cae en un reboot-loop. Por eso cualquier fallo de arranque
@@ -184,15 +188,37 @@ fn spawn_console_shell() -> std::io::Result<std::process::ExitStatus> {
         .status()
 }
 
-/// Escribe un mensaje directo a `/dev/console`, con stderr de respaldo.
+/// Escribe un mensaje directo a `/dev/console`, **a `/dev/kmsg`**
+/// (ring buffer del kernel, que se hace eco a todas las consolas
+/// registradas), y a stderr de respaldo. Así el banner se ve en VGA y
+/// serial sin importar cuál sea el último `console=` del cmdline.
 fn write_to_console(msg: &str) {
     use std::io::Write;
     if let Ok(mut f) = std::fs::OpenOptions::new().write(true).open("/dev/console") {
         let _ = f.write_all(msg.as_bytes());
     }
+    write_to_kmsg(msg);
     eprint!("{msg}");
 }
 
+/// Escribe un mensaje al `/dev/kmsg` del kernel — éste lo replica a
+/// todas las consolas registradas (`console=` del cmdline). Es el
+/// canal que usa systemd para que sus avisos se vean tanto en la VGA
+/// como en el serial.
+fn write_to_kmsg(msg: &str) {
+    use std::io::Write;
+    let Ok(mut f) = std::fs::OpenOptions::new().write(true).open("/dev/kmsg") else {
+        return;
+    };
+    // `<1>` = ALERT, prioridad alta — aparece incluso con loglevel bajo.
+    for line in msg.lines() {
+        let trimmed = line.trim_end();
+        if !trimmed.is_empty() {
+            let _ = writeln!(f, "<1>arje-zero: {trimmed}");
+        }
+    }
+}
+
 async fn primordial_loop(
     seed_card: arje_card::EntityCard,
     dev_mode: bool,
diff --git a/scripts/install-arje-as-init.sh b/scripts/install-arje-as-init.sh
index 5239d46..a913797 100755
--- a/scripts/install-arje-as-init.sh
+++ b/scripts/install-arje-as-init.sh
@@ -156,7 +156,7 @@ menuentry "arje (init=/sbin/arje-zero) — kernel $KVER" {
     insmod gzio
     insmod part_msdos
     insmod ext2
-    linux  $VMLINUZ $ROOT_OPT rw init=/sbin/arje-zero console=tty1 console=ttyS0,115200 panic=10
+    linux  $VMLINUZ $ROOT_OPT rw init=/sbin/arje-zero console=ttyS0,115200 console=tty1 panic=10
     initrd $INITRD
 }
 # END ARJE-MENUENTRY