Obtendo a largura do console usando um script bash

15

Estou com um problema em que estou tentando obter o tamanho de um terminal usando scripts. Normalmente eu usaria o comando tput colsdentro do console, no entanto, quero conseguir esse recurso usando estritamente scripts.

A partir de agora, sou capaz de detectar o console em execução e obter o caminho do arquivo. No entanto, estou lutando para usar essas informações para obter a largura do console. Eu tentei usar o comando tput, mas sou bastante novo no Linux / scripts, portanto, realmente não sei o que fazer.

A razão para fazer isso é que eu quero poder configurar uma entrada cron que notifique o console de sua largura / colunas de vez em quando.

Este é o meu código até agora:

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)

A saída normal de TERMINAL& TERMINALPATHare e , por exemplo &pts/terminalnumber/dev/pts/terminalnumberpts/0/dev/pts/0

sirgeezer21
fonte
@phk Não acho que isso ajude. A questão é como informar o driver tty dos valores reais das colunas / linhas. Aqui está para determiná-los a partir do driver tty.
roaima 29/07
Não achei que os cronempregos tivessem terminais de controle.
TMN

Respostas:

17

O tputcomando é uma excelente ferramenta, mas infelizmente não pode recuperar as configurações reais de um terminal selecionado arbitrariamente.

A razão para isso é que ele lê stdout para as características do terminal, e é também aqui que ele escreve sua resposta. Portanto, no momento em que você tenta capturar a saída, tput colsvocê também removeu a fonte de suas informações.

Felizmente, sttystdin em vez de stdout para determinar as características do terminal; portanto, é assim que você pode recuperar as informações de tamanho necessárias:

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

A propósito, é desnecessariamente complicado escrever isso como echo $(/usr/bin/tput cols).

Para qualquer construção que echo $(some_command)você está executando some_commande capturando sua saída, a qual você passa para echoa saída. Em quase todas as situações, pode-se imaginar que você acabou de executar some_commande permitir que ele produza diretamente sua saída. É mais eficiente e também mais fácil de ler.

roaima
fonte
Qual implementação / versão de tput/ nurses? O meu (ncurses 6.0.20160625) executa o TIOCGWINSZ no stderr se não puder fazê-lo no stdout. cols=$(tput cols)ou cols=$(tput cols 2<> /dev/ttyx) funciona muito bem.
Stéphane Chazelas
@ StéphaneChazelas Eu tenho o 5.9 + 20140913-1 + b1 originalmente instalado no Debian "sid". Apenas procurando uma versão mais recente agora.
roaima 29/07
1
Funciona bem com ncurses 5.7.20100313aqui. Você é positivo cols=$(tput cols 2<> /dev/tty1)não funciona para você?
Stéphane Chazelas
@ StéphaneChazelas fascinante. Você está certo: se eu afasto o stdout de um terminal, tput colsele lê do stderr . Agora preciso descobrir como reescrever minha resposta ...
roaima 29/07
1
Eu usaria stty size <"$terminal" | read rows columnsem vez de tentar analisarstty -a
Random832
13

tput colse tput linesconsulte o tamanho do terminal (do driver do dispositivo do terminal, não do próprio terminal) do dispositivo do terminal no seu stdout e, se o stdout não for um dispositivo do terminal, como no caso de cols=$(tput cols)um tubo, no stderr.

Portanto, para recuperar os valores de um dispositivo terminal arbitrário, é necessário abrir esse dispositivo no stderr de tput:

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

(aqui aberto no modo somente leitura, para tput não emitir suas mensagens de erro).

Como alternativa, você pode usar stty size. sttyconsulta o terminal no stdin:

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

Nenhum deles é padrão, portanto pode (e na prática funcionará) não funcionar em todos os sistemas. No entanto, deve ser bastante portátil para os sistemas GNU / Linux.

A inclusão de stty sizeou outro método para consultar o tamanho do terminal foi solicitada ao POSIX, mas a discussão não parece estar indo a lugar algum.

Stéphane Chazelas
fonte
8

Este script:

#!/bin/bash

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

Trabalhou aqui com absolutamente nada mais .....

Por que você está configurando uma variável de ambiente com dados? COLUNAS = $ (/ home / test / Documents / get_columns.sh)

Você está tentando obter as colunas e linhas de outro script ou tty? É isso? Ainda estranho para mim, porque você está configurando a variável de ambiente colunas para o script local ....

Luciano Andress Martini
fonte
Isso não ajuda a recuperar os valores do crontrabalho do OP para um terminal específico.
roaima 29/07
1
Ahn? O que? Agora estou mais confuso, como os scripts cronjobs podem ter largura ????? Na verdade, eles não funcionam em um terminal.
Luciano Andress Martini 29/07
Eu sei. O crontrabalho consulta um terminal específico por suas características. (Eu não sou inteiramente certo porque ele precisa fazer isso, mas é isso que o OP quer.)
roaima
@LucianoAndressMartini $ colunas e $ linhas são variáveis de bash, ele não funciona (por exemplo) no traço e elegante
ingroxd
Tks. Eu realmente sei, mas meu script é hashbang com / bin / bash, acho que você deve saber que deve usá-lo. Se você estiver usando algum unix sem bash, talvez minha resposta não seja para você.
Luciano Andress Martini
0

Minha resposta é diferente da de Roaima, pois é dinâmica. A resposta dele / dela fornece o tamanho do terminal na criação. Se você está, por exemplo, usando um gerenciador de janelas lado a lado, como i3 ou bspwm, prefere ter a largura atual do terminal. Portanto, eu uso o ssty do pacote coreutils:

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

A solução de Luciano funciona perfeitamente no xterm e no xfce4-terminal. Não sei se todos os terminais definem a variável $ COLUMNS.

Sasha
fonte
Isso não é mais dinâmico do que minha resposta. Ambos fornecem o tamanho do terminal no ponto em que você executa os comandos.
roaima