Recuperar el terminal: cómo un proceso en mitad de una tubería vuelve a leer el teclado

Fuentes: Reclaim the terminal

Cuando un programa interactivo recibe datos por una tubería (pipe), su descriptor de archivo 0 (stdin) deja de apuntar al terminal y se conecta al pipe. Esto plantea un problema: ¿cómo puede ese proceso seguir leyendo las pulsaciones del teclado del usuario? Este artículo, basado en la experimentación del desarrollador Nishant Joshi, desglosa la respuesta paso a paso mediante un programa en Rust que se encadena a sí mismo cuatro veces en una tubería y va mostrando qué proceso lee cada línea.

El primer hallazgo es que stdin y stdout pertenecen a cada proceso, no a la tubería completa: el shell simplemente conecta fd 0 y fd 1 a destinos distintos en cada etapa, y se puede inferir la posición de cada proceso con IsTerminal. El segundo es que las etapas no necesitan un canal de coordinación extra: cada proceso aguas abajo se desbloquea automáticamente cuando el anterior cierra su extremo del pipe, porque read_to_string solo termina al llegar el EOF. El tercero, y más revelador, es que abrir /dev/tty crea un nuevo descriptor que apunta al terminal de control del proceso, permitiendo leer el teclado aunque fd 0 siga conectado al pipe agotado. Esa es la técnica que herramientas como less o fzf aplican de forma implícita.

El texto también aclara malentendidos comunes: Ctrl-D no es un EOF real como el de un pipe, sino una señal del driver del terminal; exec no restablece los descriptores; y /dev/tty no nombra un dispositivo concreto, sino que se resuelve al terminal que controla al proceso. En el caso de aplicaciones con PTY, como tmux o SSH, /dev/tty apunta al lado esclavo del par seudoterminal. La conclusión práctica: para que un programa interactivo funcione dentro de una tubería basta con abrir /dev/tty y leer desde ahí una vez consumido el pipe.