Obteniendo el ancho de la consola usando un script bash


15

Me encuentro con un problema en el que intento obtener el tamaño de un terminal mediante el uso de scripts. Normalmente usaría el comando tput colsdentro de la consola, sin embargo, quiero poder lograr esta característica usando estrictamente scripts.

A partir de ahora puedo detectar la consola en ejecución y obtener su ruta de archivo. Sin embargo, estoy luchando por usar esta información para obtener el ancho de la consola. Intenté usar el comando tput, pero soy bastante nuevo en Linux / scripts, por lo que no sé qué hacer.

La razón para hacer esto es que quiero poder configurar una entrada cron que notifique a la consola su ancho / columnas de vez en cuando.

Este es mi código hasta ahora:

tty.sh

#!/bin/bash

#Get PID of terminal
#terminal.txt holds most recent PID of console in use
value=$(</home/test/Documents/terminal.txt)

#Get tty using the PID from terminal.txt
TERMINAL="$(ps h -p $value -o tty)"
echo $TERMINAL

#Use tty to get full filepath for terminal in use
TERMINALPATH=/dev/$TERMINAL
echo $TERMINALPATH

COLUMNS=$(/home/test/Documents/get_columns.sh)
echo $COLUMNS

get_columns.sh

#!/usr/bin/env bash
echo $(/usr/bin/tput cols)

La salida normal de TERMINAL& TERMINALPATHare y , por ejemplo &pts/terminalnumber/dev/pts/terminalnumberpts/0/dev/pts/0



@phk No creo que eso ayude. El problema es cómo decirle al controlador tty los valores reales de las columnas / líneas. Aquí es para determinarlos desde el controlador tty.
roaima

No pensé que los crontrabajos tuvieran terminales de control.
TMN

Respuestas:


18

El tputcomando es una herramienta excelente, pero desafortunadamente no puede recuperar la configuración real de un terminal seleccionado arbitrariamente.

La razón de esto es que lee stdout para las características del terminal, y aquí también es donde escribe su respuesta. Entonces, en el momento en que intenta capturar la salida tput cols, también ha eliminado la fuente de su información.

Afortunadamente, sttylee stdin en lugar de stdout para determinar las características del terminal, por lo que así es como puede recuperar la información de tamaño que necesita:

terminal=/dev/pts/1
columns=$(stty -a <"$terminal" | grep -Po '(?<=columns )\d+')
rows=$(stty -a <"$terminal" | grep -Po '(?<=rows )\d+')

Por cierto, es innecesariamente engorroso escribir esto como echo $(/usr/bin/tput cols).

Para cualquier construcción echo $(some_command)que esté ejecutando some_commandy capturando su salida, que luego pasa echoa la salida. En casi todas las situaciones, puede imaginar que también podría haber ejecutado some_commandy dejar que entregue su salida directamente. Es más eficiente y también más fácil de leer.


¿Qué implementación / versión de tput/ nurses? Mine (ncurses 6.0.20160625) hace el TIOCGWINSZ en stderr si no puede hacerlo en stdout. cols=$(tput cols)o cols=$(tput cols 2<> /dev/ttyx) funciona bien.
Stéphane Chazelas

@ StéphaneChazelas Tengo 5.9 + 20140913-1 + b1 instalado originalmente desde Debian "sid". Solo estoy buscando una versión más nueva ahora.
roaima

1
Funciona tan bien con ncurses 5.7.20100313aquí. ¿Eres positivo cols=$(tput cols 2<> /dev/tty1)no funciona para ti?
Stéphane Chazelas

@ StéphaneChazelas fascinante. Tienes razón: si me muevo stdout lejos de una terminal, tput colslee desde stderr . Ahora necesito encontrar la manera de volver a escribir mi respuesta ...
roaima

1
Yo usaría en stty size <"$terminal" | read rows columnslugar de tratar de analizarstty -a
Random832

13

tput colsy tput linesconsulte el tamaño del terminal (desde el controlador del dispositivo terminal, no el terminal en sí) desde el dispositivo terminal en su stdout, y si stdout no es un dispositivo terminal como en el caso de cols=$(tput cols)donde es entonces una tubería, desde stderr.

Por lo tanto, para recuperar los valores de un dispositivo terminal arbitrario, debe abrir ese dispositivo en el stderr de tput:

{ cols=$(tput cols) rows=$(tput lines); } 2< "$TERMINALPATH"

(aquí se abre en modo de solo lectura, por lo tputque no muestra sus mensajes de error allí).

Alternativamente, puede usar stty size. sttyconsulta la terminal en stdin:

read rows cols < <(stty size < "$TERMINALPATH")

Ninguno de ellos es estándar, por lo que puede (y en la práctica) no funcionará en todos los sistemas. Sin embargo, debería ser bastante portátil para los sistemas GNU / Linux.

Se stty sizesolicitó la adición de u otro método para consultar el tamaño del terminal a POSIX, pero la discusión no parece ir a ninguna parte.


8

Este guión:

#!/bin/bash

echo "The number of columns are $COLUMNS"
echo "The number of lines are $LINES"

Trabajé aquí con absolutamente nada más .....

¿Por qué está configurando una variable de entorno con datos? COLUMNS = $ (/ home / test / Documents / get_columns.sh)

¿Estás tratando de obtener las columnas y líneas de otro script o tty? ¿Es asi? Todavía es extraño para mí porque está configurando la variable de entorno de columnas para el script local ...


Esto no ayuda a recuperar los valores dentro del crontrabajo del OP para un terminal en particular.
roaima

1
Ahn? ¿Qué? Ahora estoy más confundido, ¿cómo pueden los scripts de cronjobs tener ancho? En realidad no se ejecutan en una terminal.
Luciano Andress Martini

Lo sé. El crontrabajo consulta a un terminal en particular por sus características. (No estoy completamente seguro de por qué necesita hacer esto, pero eso es lo que quiere el OP.)
roaima

@LucianoAndressMartini $ COLUMNS y $ LINES son variables bash, no funciona (por ejemplo) en dash y posh
ingroxd

Tks Realmente lo sé, pero mi script es hashbang con / bin / bash, creo que se supone que debes saber que debes usarlo. Si está utilizando unix sin bash, tal vez mi respuesta no sea para usted.
Luciano Andress Martini

1

Mi respuesta es diferente a la de Roaima, ya que es dinámica. Su respuesta le da el tamaño del terminal en la creación. Si, por ejemplo, está utilizando un administrador de ventanas de mosaico, como i3 o bspwm, preferiría tener el ancho actual del terminal. Por lo tanto, uso ssty del paquete coreutils:

#!/bin/bash
stty size | awk '{print $2}'

La solución de Luciano funciona perfectamente en xterm y xfce4-terminal. No sé si todas las terminales establecen la variable $ COLUMNS.


Esto no es más dinámico que mi respuesta. Ambos le dan el tamaño del terminal en el punto donde ejecuta los comandos.
roaima
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.