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>
This commit is contained in:
@@ -87,6 +87,10 @@ fn main() -> anyhow::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
info!("ente-zero despierta como PID 1");
|
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
|
// Doctrina dura: PID 1 NUNCA puede salir — el kernel haría panic
|
||||||
// ("Attempted to kill init") y, con `panic=N` en el cmdline, la
|
// ("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
|
// 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()
|
.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) {
|
fn write_to_console(msg: &str) {
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
if let Ok(mut f) = std::fs::OpenOptions::new().write(true).open("/dev/console") {
|
if let Ok(mut f) = std::fs::OpenOptions::new().write(true).open("/dev/console") {
|
||||||
let _ = f.write_all(msg.as_bytes());
|
let _ = f.write_all(msg.as_bytes());
|
||||||
}
|
}
|
||||||
|
write_to_kmsg(msg);
|
||||||
eprint!("{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(
|
async fn primordial_loop(
|
||||||
seed_card: arje_card::EntityCard,
|
seed_card: arje_card::EntityCard,
|
||||||
dev_mode: bool,
|
dev_mode: bool,
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ menuentry "arje (init=/sbin/arje-zero) — kernel $KVER" {
|
|||||||
insmod gzio
|
insmod gzio
|
||||||
insmod part_msdos
|
insmod part_msdos
|
||||||
insmod ext2
|
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
|
initrd $INITRD
|
||||||
}
|
}
|
||||||
# END ARJE-MENUENTRY
|
# END ARJE-MENUENTRY
|
||||||
|
|||||||
Reference in New Issue
Block a user