Qué es OSC 3008: señalización de contexto de terminal en systemd y solución de salida basura

Explicación de UAPI.15 OSC 3008 Hierarchical Context Signalling: qué hace, qué datos envía, dónde lo usa systemd y cómo diagnosticar o desactivar la salida basura en terminales incompatibles.

OSC 3008, cuyo nombre completo es Hierarchical Context Signalling, es UAPI.15 dentro de las especificaciones de UAPI Group. Define un conjunto de secuencias de control de terminal que permiten a los programas informar al emulador de terminal sobre la jerarquía de contexto actual dentro de una sesión.

En términos sencillos, intenta responder una pregunta cada vez más común en terminales Linux modernos: ¿en qué capa estás realmente?

Por ejemplo, puedes hacer SSH desde tu máquina local a un servidor, entrar en un contenedor y después usar run0 o una herramienta similar para ejecutar un comando con privilegios elevados. Para ti sigue siendo una única ventana de terminal. Para el emulador de terminal, sin una señal adicional, es difícil saber si la salida actual viene de la máquina local, del host remoto, de un contenedor o de un comando elevado.

OSC 3008 está diseñado para este tipo de escenario. La especificación oficial de UAPI indica que permite a los emuladores de terminal rastrear la jerarquía de contexto del contenido actual en pantalla. systemd también ofrece una implementación, normalmente mediante un script llamado 80-systemd-osc-context.sh.

Referencias oficiales:

Por qué hace falta OSC 3008

Los terminales tradicionales muestran la salida de los programas. Como mucho, ayudan a distinguir entornos mediante títulos, colores y prompts. El problema es que las sesiones modernas de terminal suelen estar anidadas:

1
local shell -> SSH remote server -> Docker/Podman/systemd-nspawn container -> run0 elevated command

Si todo depende de PS1, aparecen varios problemas:

  1. El prompt solo describe el shell actual y no expresa bien toda la jerarquía.
  2. Distintos shells, distribuciones y configuraciones de usuario pueden sobrescribirse entre sí.
  3. El emulador de terminal no puede saber de forma fiable a qué contexto pertenece cada salida.
  4. Algunas secuencias de control aparecen como basura visible en terminales incompatibles.

OSC 3008 ofrece un enfoque más estructurado: el programa que entra en un contexto envía una secuencia start, y el programa que sale envía una secuencia end. Tras analizarlas, el emulador de terminal puede saber a qué nodo de contexto pertenece la salida actual.

Qué información envía

OSC 3008 es un conjunto de secuencias de escape OSC. La especificación define dos comandos centrales:

1
2
OSC "3008;start=..." ST
OSC "3008;end=..." ST

start indica que un contexto empieza, se actualiza o vuelve a ser el contexto actual. end indica que un contexto termina.

Cada contexto puede incluir campos de metadatos. Entre los campos comunes están:

  1. type=: tipo de contexto, como shell, command, remote, container, vm o elevate.
  2. user=: usuario UNIX que emite la secuencia.
  3. hostname=: nombre del host.
  4. machineid=: ID de máquina de /etc/machine-id.
  5. bootid=: ID de arranque de /proc/sys/kernel/random/boot_id.
  6. pid=: PID del proceso que emite la secuencia.
  7. comm=: nombre del proceso.
  8. cwd=: directorio de trabajo actual, sobre todo para shell o command.
  9. cmdline=: línea de comandos invocada de forma interactiva.
  10. container= y vm=: nombres de contenedor o máquina virtual.
  11. targetuser= y targethost=: usuario destino u host remoto destino.

Estos campos no están pensados para que el usuario los lea directamente, sino para que los analice el emulador de terminal. Un terminal compatible consume estas secuencias y las usa para mejorar la interfaz.

Qué ventajas puede aportar

Si el emulador de terminal soporta OSC 3008, puede hacer cosas más inteligentes.

Primero, puede marcar salidas de contextos distintos. Por ejemplo, salida de un contenedor, salida de un comando elevado y salida de SSH remoto pueden tener fondos, bordes o avisos diferentes.

Segundo, puede mostrar una ruta jerárquica. El terminal puede saber que la sesión actual está aproximadamente en:

1
local machine -> remote host -> container -> root command

Esto es más estable que depender solo del título de la ventana o de PS1.

Tercero, puede ayudar con títulos de ventana, pestañas y menús contextuales. El terminal puede actualizar el título de la pestaña según el contexto actual, o permitir acciones como abrir un shell en el mismo directorio de una salida concreta.

Cuarto, puede reducir errores. Si estás dentro de un contenedor de producción y ejecutando comandos como root, el terminal puede mostrar un aviso más visible y reducir la probabilidad de ejecutar comandos peligrosos en el entorno equivocado.

Cómo lo integra systemd

La implementación de systemd vive principalmente en 80-systemd-osc-context.sh. Este script se carga mediante el mecanismo de profile y configura funciones y hooks de prompt en entornos Bash interactivos.

Las rutas comunes pueden ser:

1
2
/etc/profile.d/80-systemd-osc-context.sh
/usr/lib/systemd/profile.d/80-systemd-osc-context.sh

La ubicación exacta depende de la distribución. Los comentarios del código fuente de systemd explican que este archivo puede activarse mediante systemd-tmpfiles, que lo enlaza en /etc/profile.d/.

En Bash usa nombres de función como:

1
2
3
__systemd_osc_context_escape
__systemd_osc_context_common
__systemd_osc_context_precmdline

También afecta a PROMPT_COMMAND y PS0. PS0 se expande después de que Bash lea un comando y antes de ejecutarlo. Por eso algunos terminales incompatibles pueden mostrar un texto largo 3008;start=... antes de cada comando.

Por qué algunos terminales muestran basura

Normalmente, un emulador de terminal debería analizar OSC 3008 como secuencia de control y no mostrarlo directamente.

Pero si el terminal no reconoce OSC 3008, o una capa intermedia filtra, escapa o rompe los caracteres de control, el contenido bruto puede aparecer en pantalla. Los casos comunes incluyen:

  1. Emuladores de terminal antiguos.
  2. Clientes SSH que aún no se han adaptado a OSC 3008.
  3. Bastiones web o terminales de navegador, incluidas algunas instalaciones de Apache Guacamole.
  4. Entornos con soporte OSC limitado, como Emacs term.el, terminales serie o minicom.
  5. Reenvíos de varias capas donde una capa intermedia daña la secuencia de control.

En ese caso puedes ver algo parecido a:

1
]3008;start=...;type=command;cwd=...

O cadenas largas con machineid=, bootid=, pid=, comm= y cwd=. No son salida normal de un programa; son señales de contexto que el terminal debía procesar.

Cómo saber si es OSC 3008

Mira tres pistas.

Primero, si la basura incluye 3008;start= o 3008;end=.

Segundo, si aparece antes o después de ejecutar comandos, especialmente cada vez que pulsas Enter.

Tercero, si el sistema actual cargó las funciones OSC de systemd:

1
declare -f __systemd_osc_context_precmdline

Si ves una definición de función, el shell actual cargó esa lógica.

También puedes comprobar el archivo de profile:

1
ls -l /etc/profile.d/80-systemd-osc-context.sh

Si esa ruta existe y tu terminal no soporta OSC 3008, es muy probable que la salida basura venga de ahí.

Solución temporal

Si solo te molesta en la sesión actual, puedes sobrescribir las funciones relacionadas y limpiar PS0:

1
2
3
4
__systemd_osc_context_precmdline() { :; }
__systemd_osc_context_common() { :; }
__systemd_osc_context_escape() { :; }
PS0=""

Si quieres hacerlo automáticamente solo en sesiones SSH, ponlo en ~/.bashrc:

1
2
3
4
5
6
7
8
if [[ -n "$SSH_CLIENT" || -n "$SSH_TTY" || -n "$SSH_CONNECTION" ]]; then
    if declare -f __systemd_osc_context_precmdline >/dev/null; then
        __systemd_osc_context_precmdline() { :; }
        __systemd_osc_context_common() { :; }
        __systemd_osc_context_escape() { :; }
        PS0=""
    fi
fi

Este método tiene poco alcance. No cambia archivos profile del sistema y es fácil de retirar.

Desactivación a nivel de sistema

Si confirmas que el entorno de terminal de esta máquina es generalmente incompatible con OSC 3008, puedes considerar desactivarlo a nivel de sistema. Ten cuidado: afecta a todos los usuarios y sesiones de inicio.

La idea descrita en los comentarios del script de systemd es eliminar el enlace simbólico /etc/profile.d/80-systemd-osc-context.sh y enmascarar el fragmento tmpfiles correspondiente para que no se vuelva a crear.

Puedes usar un comando como este:

1
2
3
test -h /etc/profile.d/80-systemd-osc-context.sh && \
rm -v /etc/profile.d/80-systemd-osc-context.sh && \
ln -s /dev/null /etc/tmpfiles.d/20-systemd-osc-context.conf

Esto es más pesado que cambiar ~/.bashrc. Prueba primero la solución temporal para confirmar que el problema realmente viene de OSC 3008, y luego decide si la desactivación del sistema tiene sentido.

Si solo tu cliente SSH personal es incompatible, no empieces cambiando la configuración global. Es preferible usar tu propio ~/.bashrc o configurar un comando de limpieza posterior al inicio de sesión en el cliente SSH.

Actualizar el terminal o desactivar OSC 3008

Si usas un terminal moderno que ya soporta OSC 3008, es mejor conservar esta capacidad. En el futuro puede hacer más clara la visualización de shells remotos, contenedores, máquinas virtuales y comandos elevados.

Si tu entorno real es un bastión, una consola serie, un terminal antiguo o un Web SSH que no puedes actualizar pronto, suprimirlo es más práctico. Para la mayoría de tareas de operaciones, una salida limpia y legible es más importante que una visualización de contexto mejorada.

Puedes seguir este orden:

  1. Si puedes actualizar el emulador de terminal, hazlo primero.
  2. Si no puedes actualizar y solo te afecta a ti, suprime la salida en ~/.bashrc o en el comando posterior al inicio de sesión del cliente.
  3. Si afecta a toda la máquina, considera eliminar /etc/profile.d/80-systemd-osc-context.sh y enmascarar el fragmento tmpfiles.

Conclusión breve

OSC 3008 no es malware ni salida aleatoria de un programa. Es señalización de contexto de terminal definida por UAPI.15, pensada para que el terminal entienda la jerarquía entre shells, SSH, contenedores, máquinas virtuales y comandos elevados.

El problema real suele ser la compatibilidad. Un terminal compatible lo analiza automáticamente. Uno incompatible puede mostrar la secuencia de control como basura.

Si ves contenido como 3008;start=, machineid=, bootid= o cwd=, primero comprueba si lo inyectó 80-systemd-osc-context.sh de systemd. Después, según el alcance del impacto, elige una solución temporal, una corrección en tu .bashrc personal o una desactivación a nivel de sistema.

记录并分享
Creado con Hugo
Tema Stack diseñado por Jimmy