Lo hice y lo entendí

El blog de Vicente Navarro
17 nov

Emuladores de terminal. GNU screen: El multiplexador de sesiones de terminal.

A finales de los 70, los monstruosos ordenadores de la época comenzaron a usar terminales serie para la consola y la entrada salida estándar (teclado y pantalla). Antes de ellos, los ordenadores interactuaban con el usuario usando teletipos (teletype: TTY, ¿te suenan de algo estas siglas?). Los terminales pioneros, tal y como los conocemos ahora, fueron el DEC VT52 y el DEC VT100, por allá por 1978. Éste era su aspecto:

Otros fabricantes desarrollaron otros tipos de terminales, con el mismo concepto, pero incompatibles con otros sistemas, como este HP 700/96, que aún se sigue usando en algunos CPD hoy en día:

Los ordenadores personales, como el PC y los Apple o los Commodore, Spectrum, Amstrad CPC, etc. siguieron otro camino para mostrar la información al usuario, ya que, o bien usaban un sistema de vídeo propietario para mostrar texto y gráficos (p.e. MDA o VGA), o bien se conectaban directamente al televisor.

Los grandes servidores UNIX (basados en AIX, HP-UX, Solaris, etc.) o similares (por ejemplo, basados en OpenVMS, o z/OS) han llegado a nuestros días permitiendo la conexión de un terminal serie para usar la consola, pero cada día es más infrecuente su uso, ya que han sido sustituidos por consolas LAN (accedemos por Telnet o por SSH a una dirección IP diferente a la propia del sistema) o por consolas Web (una página web donde nos aparece la consola), que, por supuesto, nos permiten interactuar con la máquina incluso durante el arranque y la parada.

Hoy en día los terminales serie están bastante en desuso. Sin embargo, los emuladores de terminal están en pleno apogeo, bien sean para conectarnos por Telnet, por SSH, o, por supuesto, por el puerto serie/módem (ya lo vimos en Configurar Linux para permitir el acceso remoto por módem a la consola y por RAS/PPP). Por cierto, ¿qué tipo de terminal emulan la mayoría de emuladores de terminal como mínimo? Pues, por supuesto, el famoso VT100. Pero como otros fabricantes hicieron otros terminales con sus propios protocolos, secuencias de escape y capacidades, hay múltiples tipos de emuladores de terminal. Las emulaciones de terminal ansi y vt100 (y tal vez xterm) son las más usadas.

Tal y como vimos en Terminales para Cygwin. Notas sobre Terminfo y Termcap., los sistemas UNIX tienen una pequeña base de datos de tipos de terminales y una librería para poder interactuar con la mayoría de ellos sin tener que conocer sus peculiaridades. En los sistemas que usan Terminfo, por ejemplo, encontraremos en /usr/share/terminfo una gran cantidad de ficheros de descripción de muchos tipos de terminal en formato binario.

Si usamos Telnet o SSH y necesitamos abrir varias sesiones contra un sistema, no tendremos ningún problema. Podemos abrir tantas como sean necesarias. Si estamos trabajando en el entorno X Window System, tampoco tendremos ningún problema: podemos abrir tantos xterm, Konsole, o gnome-terminal como queramos. Los emuladores de terminal más modernos permiten incluso pestañas, para tener muchas sesiones abiertas en la misma ventana de la aplicación. Y no olvidemos que en la consola de texto normal de Linux, también podemos tener varias sesiones cambiando de TTY con ALT+Fx.

Sin embargo, en la época en la que se usaban terminales serie de verdad o, incluso hoy en día, si te conectas a la LAN console o la Web console de un sistema UNIX, o si te conectas por módem o por cable serie a un Linux en un PC, sólo puedes tener una única sesión de shell en el sistema.

Es en esos casos en los que necesitas una herramienta de multiplexación de terminales, como el GNU screen. Son herramientas que permiten, dentro de la sesión de terminal actual, crear múltiples sesiones funcionando todas a la vez. En HP-UX, por ejemplo, hay una herramienta similar, el tsm, para ejecutar varias tareas en paralelo si nos conectamos a la consola, que es única y no se puede compartir.

Para comenzar a usarla, sólo tenemos que escribir screen y pulsar la tecla de espacio para aceptar la licencia. Estamos dentro de screen pero sólo tenemos una sesión. Si pulsamos la combinación de teclas CONTROL+A MAYUSCULAS+2 (o lo que es lo mismo, CONTROL+A "), nos aparecerá una lista de todas las sesiones abiertas, que en este momento será una sola:

Num Name                                               Flags

  0 bash                                                   $

Si ahora pulsamos la combinación de teclas CONTROL+A C, crearemos una nueva sesión paralela a la anterior y podremos elegir entre cualquiera de las dos pulsando CONTROL+A " y luego eligiendo una de ellas con los cursores y la tecla de RETURN:

Num Name                                               Flags

  0 bash                                                   $
  1 bash                                                   $

Con CONTROL+A MAYUSCULAS+A podemos cambiar el nombre de la sesión actual para distinguirlas unas de otras:

Num Name                                               Flags

  0 top                                                    $
  1 Compilando el kernel                                   $
  2 man screen                                             $

El nombre nos sirve también para, pulsando CONTROL+A ', elegir el nombre o el número de la sesión que queremos activar. También podemos elegir la sesión por número con CONTROL+A 0CONTROL+A 9 o ir a la sesión siguiente con CONTROL+A ESPACIO o a la anterior con CONTROL+A BORRAR.

Podemos ver todas las combinaciones de teclas en la página de man de screen.

Una combinación curiosa es el CONTROL+A H, que vuelca el texto que está mostrando el terminal en ese momento en un fichero de texto con nombre hardcopy.n, donde n es el número de sesión de screen. Una aplicación muy útil, sin duda alguna, especialmente cuando estamos trabajando en la consola y no tenemos ninguna posibilidad de copiar y pegar texto fácilmente.

Pero la funcionalidad de multiplexar sesiones de screen, o incluso la de hacer una captura del texto de la pantalla, aunque en determinadas ocasiones nos puede resultar muy útil, no son lo que, a mi parecer, convierte a screen en casi una “killer app“.

La funcionalidad clave para mí es la posibilidad de desenganchar (detach) las sesiones de screen del terminal en el que estamos para volver a engancharnos (attach) en otro terminal.

Por ejemplo, yo conozco personas que para hacer algún trabajo de mantenimiento delicado con un sistema UNIX al que se tienen que conectar por SSH o telnet tras establecer una conexión VPN, en lugar de hacer la conexión directamente, primero se conectan a un Windows con Terminal Services y se conectan con PuTTY desde él. Así, si la conexión VPN se cae, algo que es relativamente fácil que ocurra, la tarea no se interrumpe al cerrarse la conexión de telnet o SSH, puesto que sigue ejecutándose desde el Windows al que podemos reconectarnos cuando sea posible.

Si esa tarea la hubiéramos lanzado con nohup (Sobre la señal SIGHUP: nohup, disown, trap), no tendríamos peligro de interrumpir la tarea aunque se cerrara, pero si la aplicación es interactiva, o si usa librarías de terminal como ncurses, no es una posibilidad.

Con screen podemos hacer algo parecido a lo que hacemos con nohup pero con sesiones de terminal completas. Algo parecido a lo que nos permite hacer el Terminal Server de desconectarnos y conectarnos cuantas veces queramos sin cerrar las aplicaciones, pero con nuestras sesiones de terminal.

Para desenganchar un screen del terminal usaremos la combinación de teclas CONTROL+A D:

$ screen
[detached]

ahora podremos ver las sesiones de screen “desenganchadas” con “screen -ls“:

$ screen -ls
There is a screen on:
	9435.pts-0.sistema	(11/17/2008 08:45:19 PM)	(Detached)
1 Socket in /var/run/screen/S-vicente.

y engancharnos de nuevo a ella con “screen -r“. Si hay más de una sesión “desenganchada”, nos pedirá que especifiquemos una en concreto tras listarnos las existentes:

$ screen -r
There are several suitable screens on:
	11170.pts-0.sistema	(11/17/2008 09:27:38 PM)	(Detached)
	9435.pts-0.sistema	(11/17/2008 08:45:19 PM)	(Detached)
Type "screen [-d] -r [pid.]tty.host" to resume one of them.

$ screen -r 11170.pts-0.sistema

De hecho, no hace falta ni siquiera desengancharnos de screen para que las sesiones se conserven en caso de desconexión de nuestro terminal. Si el terminal que contiene a screen muere, el screen se “desenganchará” automáticamente y podremos volver a “engancharnos” desde otro terminal cuando podamos.

Imaginemos que estamos en el trabajo configurando un sistema UNIX, algo que no puede esperar. No hemos acabado, pero tenemos que irnos a casa ya por una urgencia. Pues si estábamos trabajando con screen, podemos “desenganchar” la sesión y más tarde, cuando nos podamos conectar a través de VPN desde casa, nos volvemos a “enganchar” a la sesión y seguimos exactamente donde nos habíamos quedado. ¿No es increíble? screen nos mantiene nuestras sesiones de terminal vivas pase lo que pase.

Y no se vayan todavía, aún hay más… Resulta que puede que lancemos screen desde un xterm (gnome-terminal) y que después nos queramos reconectar desde la consola de Linux, desde un PuTTY, o desde cualquier otro tipo de emulador de terminal. Pues screen nos lo permite. A las aplicaciones que se ejecutan desde dentro, les presenta un interfaz VT100/ANSI, y screen se ocupa de traducir de un tipo de terminal a otro:

       Screen is a full-screen window manager that multiplexes a physical ter‐
       minal between several processes (typically interactive  shells).   Each
       virtual terminal provides the functions of a DEC VT100 terminal and, in
       addition, several control functions from the ISO 6429  (ECMA  48,  ANSI
       X3.64)  and ISO 2022 standards (e.g. insert/delete line and support for
       multiple character sets).

Como ejemplo, esto tiene la curiosa utilidad, que nos apuntó Dawud Medina en Terminales para Cygwin. Notas sobre Terminfo y Termcap., de poder usar Terminator, que usa una emulación de terminal propietaria (terminator), para conectarnos a sistemas remotos que no conocen esta emulación gracias a screen, ya que nosotros ejecutamos screen dentro de Terminator, y screen presenta una emulación de terminal VT100 a la aplicación final, que no se entera de que está en un terminal Terminator.

Por cierto, dentro de screen, $TERM no es vt100:

$ echo $TERM
screen

Pero eso tiene una explicación, que es que podemos cambiarlo cuando queramos, ya que TERM=screen es totalmente compatible con TERM=vt100:

       In each window’s environment screen opens, the $TERM variable is set to
       "screen" by default.  But when no description for "screen" is installed
       in the local termcap or terminfo data base, you set $TERM to  -  say  -
       "vt100".  This  won’t do much harm, as screen is VT100/ANSI compatible.
       The use of the "term" command is discouraged for  non-default  purpose.
       That  is,  one  may want to specify special $TERM settings (e.g. vt100)
       for the next "screen rlogin  othermachine"  command.  Use  the  command
       "screen -T vt100 rlogin othermachine" rather than setting and resetting
       the default.

:wq

Entradas relacionadas

21 Comentarios a “Emuladores de terminal. GNU screen: El multiplexador de sesiones de terminal.”

  • Tne dice:

    Buen articulo. La verdad yo no sabría vivir sin el.
    Animo a los lectores que busque por google y verán que esto es un grano en un desierto

    Para los amantes de la consola y el texto, Screen es herramienta cotidiana

  • trinux dice:

    ¡¡Demonios!! para ya. Tengo tres artículos tuyos, incluido este, pendientes de leer con tranquilidad. Bueno, te perdono: ¡¡gracias!! :)

    P.S.: ¡No pares!

  • Raist dice:

    Para el copiado y pegado , si requiere mas exactitud , con el servidor para mouse gpm , resaltando lo necesario , y con click derecho , ya hemos copiado y pegado . Para mis limitadas necesidades , y poco mas conocimientos , puede que me sea mas interesante twin ,aunque este casi parece un window manager . Un post como todos los tuyos , excelente y sumamente interesante ;) .

  • davidp dice:

    screen es una de esas herramientas que hasta que no la usas un par de veces, no te das cuenta de lo útil que es. Llega un momento en el que te preguntas cómo has podido vivir hasta ahora sin utilizarla.

  • perico dice:

    No es del todo cierto que te recupere la sesión cuando desenganchas un terminal.

    Me ha pasado varias veces: Dejarme el Vim abierto con la ventana partida y al intentar enganchar esa sesión en otro sitio me aparece el Vim muerto, creo que es por que la ventana del terminal no era del mismo tamaño y se hace la picha un lío.

    Eso sí, screen es un salvavida. Alguna vez estando ejecutando algo importante le he dado a cerrar sesión sin queror o incluso he matado las X por error y al volver a iniciarse ¡no se ha perdido nada!

    Por cierto las primeras veces te ocurrirá que cierras el terminal pero no has cerrado la sesión screen y por tanto se queda en segundo plano. El primer día cuando me dí cuenta tenía 4 o 5 screens corriendo en segundo plano. Hay que salir correctamente de screen o en su defecto luego cargar una sesión ya iniciada para no acumular sesiones inútiles.

  • @Tne ¡Gracias!

    @trinux ¡Vaya! Ya siento darte tanto trabajo ;-)

    @Raist Sí, para copiar y pegar el gpm también es una opción muy válida cuando estamos en la consola de Linux. Por otra parte, no conocía el Twin, tendré que probarlo.

    @david Así es :-)

    @perico Me sorprende lo que me dices del vim. Dentro de screen el tipo de terminal siempre es el mismo, y el vim sabe gestionar bien los cambios de dimensiones del terminal. Supongo que no te pasará siempre, sino sólo en determinadas circunstancias indeterminadas, ¿verdad?

  • perico dice:

    @Coco me ocurre de vez en cuando. Por ejemplo, acabo de hacer esto:

    abrir konsole
    ejecutar screen
    ejecutar vim
    maximizar la ventana de console
    parto vim en 2 buffer verticalmente (^W, v)
    cierro konsole a saco
    abro otro konsole (no está maximizado)
    cargo la sesión anterior screen -dr (aparece vim, el buffer de la derecha no se ve porque no cabe en la ventana)
    al pulsar en algún lugar de la ventana el vim muere con el error “Bad window” y un chorro de errores de x11

    Lo he probado y la primera vez ha dado el error ese de Bad window, lo he probado otras 4 veces más y no ha fallado. Supongo que será que Vim utiliza alguna función de x11 si detecta que está en una ventana y el cambio repentino de descriptor de ventana no lo traga bien.

    Por cierto, ¿no sabrás como dividir con screen la ventana en 2 verticalmente? sólo he conseguido partirla horizontalmente y no es muy cómodo.

    Saludos

  • @perico Pues no sé, he probado justamente eso mismo pero con gnome-terminal y no me ha dado problemas. A ver si instalo Konsole y lo pruebo…

    Y sobre dividir la pantalla, no lo sé, la verdad es que no lo he usado nunca. Lo siento.

  • AlBundy dice:

    GNU screen: una pequeña joya, que usamos una “inmensa minoría”.

    @perico El vertical split (v-split mode) es un añadido relativamente reciente en la historia de GNU screen, que siempre ha dado problemas de lentitud debido a que el redibujado de los v-splits en un terminal es más complejo que el de los splits tradicionales (horizontal splits).

    *Very bad/slow redraw with vertical split
    *New screen features available

    Si no me equivoco, el vertical split sólo se incluye en las versiones de desarrollo de GNU screen, que antes se obtenían mediante CVS desde cvs.savannah.gnu.org, y ahora se obtienen mediante GIT desde git.savannah.gnu.org

    *New screen features available
    *Latest version of screen
    *Screen 4.0.3 @ GNU FTP (existing release)

    Desconozco si los paquetes de Screen que llevan las distros actuales usan el código estable o el de desarrollo.

    Después de estar unos años a medio gas, el desarrollo de Screen tiene un futuro muy interesante.

    -Tenemos nuevo desarrollador jefe (Micah J. Cowan)

    -Se está buscando la forma de portar mucho del código en C a un lenguaje de script (Lua o similar), de manera que el código sea más fácil de mantener y de extender:

    Scripting Support for Screen

    -Se quiere rediseñar la ENORME página del manual, para hacerla más fácil de mantener:

    Man-writing volunteers?

  • @AlBundy Anonadado dejádome has ;-) ¡Sí que estás puesto en el tema del screen! Ya veo que sigues muy de cerca su lista de distribución.

    ¡Muchas gracias por tan interesante comentario!

    PD: Me he permitido corregir los enlaces del comentario y rescatarlo de la cola de Akismet, que lo había cazado como “spam”.

  • AlBundy dice:

    @Supercoco

    Supongo que los enlaces habrán quedado fatal. El marcado HTML no es lo mío ;-) Tendré que leerme algún tutorial.

    Tenía la intención de corregirlos sobre la vista preliminar, pero después de pulsar el botón de enviar no ha aparecido ninguna vista dónde editar. Supongo que habrá sido cosa de Akismet.

    Mil disculpas.

  • Trauma dice:

    Screen es una utilidad que utilizé hace tiempo, cuando estaba empezando con Linux, y, ciertamente, facilitaba muchisimo el trabajo. Tener varias ventanas abiertas, una con un cliente chat, otra con el links buscando algo en la documentación, y una tercera con el mc editando un archivo de configuración, era el pan nuestro de cada dia.
    Pasado un tiempo, me acostumbré a las X, y, como bién dices, los emuladores de terminal para X suelen permitir varias pestañas, o, directamente, abrir varias ventanas.
    No obstante, la capacidad de screen de permitir des/conectar con sesiones previamente creadas hizo que siguiera usandolo para controlar varios demonios o varias tareas largas, de los cuales el único que aún utilizo es el rtorrent (de uso evidente).
    No obstante, para estas tareas en las que no son es necesario realizar varias sesiones a la vez, utilizo, desde que lo descubrí, el programa ‘dtach’; permite, al igual que screen, desconectar de la sesion y recuperarla más tarde, sin interferir en el funcionamiento de lo que estemos ejecutanto. No permite la ejecución simultanea de varias aplicaciones. Cada session de dtach tan solo puede ejecutar un programa; no obstante, podemos ejecutar varias sessiones en segundo plano y desconectar / conectar con la que queramos en cada momento, identificadonlas mediante sockets unix con nombre ubicados en el directorio que queramos.
    La mayor ventaja de dtach contra screen es su tamaño, mucho más pequeño al no necesitar toda la logica de control de ventanas, y, por esa misma razón, es más simple de utilizar. Una orden para iniciar session, una combinación de teclas para desconectarla, y otra orden para reconectar sesiones previamente creadas.
    En un programa que recomiendo, teniendo siempre presente sus limitaciones.

  • @Traume Muchas gracias por tu comentario. Me apunto lo del dtach, no lo he probado pero lo haré :-)

  • Berto dice:

    sin más: con una buena configuracion todo resulta un poco más facil…

    @bertocasa (amelgar) ~ :: cat .screenrc
    #kill startup message
    startup_message off

    defscrollback 1024
    hardstatus on
    hardstatus alwayslastline

    #hardstatus string “%{.bW}%-w%{.rW}%n %t%{-}%+w %=%{..G} %H %{..Y} %m/%d %C%a ”

    hardstatus string ‘%{= kg}[ %{G}%H %{g}][%= %{= kw}%?%-Lw%?%{=b kR}(%{W}%n*%f %t%?(%u)%?%{=b kR})%{= kw}%?%+Lw%?%?%= %{g}]%{=b C}[ %d %M %c ]%{W}’

    screen -t rOOt 0 su –
    screen -t ncmpc 1 bash
    screen -t terminal 2 bash
    screen -t MidnightComander 3 mc
    screen -t vimTerm 4 bash
    screen -t terminal 5 bash
    @bertocasa (amelgar) ~ ::

  • @Berto Es una configuración muy interesante. ¡Muchas gracias por compartirla aquí!

  • JuanPablo dice:

    una duda, ¿es posible que al encender el equipo e iniciar screen recuerde las sesiones anteriores? asi como vim recuerda el ultimo archivo que estabas editando

  • @JuanPablo Fíjate en el comentario de Berto anterior al tuyo. Él nos mostraba cómo arrancar cada vez con las mismas sesiones y las mismas aplicaciones. Lo que no se puede hacer, claro, es que las aplicaciones sigan en el mismo punto en el que las dejaste tras el reinicio.

  • JuanPablo dice:

    @Super Coco
    tienes razon en la respuesta de Berto, el dice como arrancar cada vez con las mismas aplicaciones.
    mi pregunta era como recuperar el estado anterior, por ejemplo si en screen tenias 3 sessiones abiertas en en directorios diferentes, al apagar y encender denuevo, screen abra esas mismas en los mismos directorios.

    no quiero ser cargante pero voy al volver a citar el caso de vim, este guarda las sessiones con agregar algunas lineas al vimrc:

    “guardar y abrir ultima session
    function! SaveSession()
    execute ‘mksession! $VIMHOME/sessions/session.vim’
    endfunction
    function! LoadSession()
    if argc() == 0
    execute ‘source $VIMHOME/sessions/session.vim’
    endif
    endfunction
    autocmd VimEnter * call LoadSession()
    autocmd VimLeave * call SaveSession()

  • @JuanPablo No conocía las posibilidades de configuración tan avanzadas de vim que muestras. Gracias.

    No sé si te entiendo bien, pero partiendo de lo que mostraba Berto, ¿tal vez lo que quieres hacer es algo como?:

    screen -t 'vi en /tmp' bash -c '(cd /tmp; vim fichero)'

    Esto es, que al entrar en screen te restaure un vi sobre un fichero determinado en el directorio de trabajo que tú quieres.

  • JuanPablo dice:

    @Super Coco
    te recomiendo el libro “Hacking Vim” de Kim Schulz.

    screen -t ‘vi en /tmp’ bash -c ‘(cd /tmp; vim fichero)’
    tu linea para screenrc lo reduces a
    screen -t ‘vim’ vim
    y las lineas de vimrc que anteriormente comente

    pero mi pregunta no es respecto a las secciones de vim, sino como tener un inicio “dinámico” de screen dependiendo de las actividades anteriores

    no e encontrado una opción así, al parecer la única solución sera un script que modifique el screenrc + un aliias

    alguna otra idea ?

  • @JuanPablo Vale, creo que ya te he entendido. Que yo sepa, no se puede hacer lo que comentas, pero que yo no lo sepa no significa con total seguridad que no se pueda hacer ;-) .

    ¡Gracias por la información sobre vim!

Tema LHYLE09, creado por Vicente Navarro