Ottenere la larghezza della console usando uno script bash


15

Sto riscontrando un problema in cui sto cercando di ottenere le dimensioni di un terminale utilizzando gli script. Normalmente userei il comando tput colsall'interno della console, tuttavia voglio essere in grado di realizzare questa funzione usando rigorosamente gli script.

A partire da ora sono in grado di rilevare la console in esecuzione e ottenere il suo percorso di file. Tuttavia, faccio fatica a usare queste informazioni per ottenere la larghezza della console. Ho provato a usare il comando tput, ma sono abbastanza nuovo su Linux / script, quindi non so davvero cosa fare.

Il motivo per questo è che voglio essere in grado di impostare una voce cron che notifica la console della sua larghezza / colonne ogni tanto.

Questo è il mio codice finora:

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)

Il normale output di TERMINAL& TERMINALPATHare e , ad esempio &pts/terminalnumber/dev/pts/terminalnumberpts/0/dev/pts/0



@phk Non penso che aiuti. Il problema è come dire al driver tty dei valori effettivi per colonne / linee. Qui è per determinarli dal driver tty.
roaima,

Non pensavo che i cronlavori avessero terminali di controllo.
TMN,

Risposte:


18

Il tputcomando è uno strumento eccellente, ma sfortunatamente non può recuperare le impostazioni effettive per un terminale selezionato arbitrariamente.

La ragione di ciò è che legge stdout per le caratteristiche del terminale, ed è anche qui che scrive la sua risposta. Quindi, nel momento in cui provi a catturare l'output, tput colshai rimosso anche la fonte delle sue informazioni.

Fortunatamente, sttylegge stdin piuttosto che stdout per la sua determinazione delle caratteristiche del terminale, quindi è così che puoi recuperare le informazioni sulla dimensione che ti servono:

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

A proposito, è inutilmente ingombrante scrivere questo come echo $(/usr/bin/tput cols).

Per qualsiasi costrutto echo $(some_command)che stai eseguendo some_commande acquisendo il suo output, che poi passi echoall'output. In quasi ogni situazione puoi immaginare che potresti anche aver appena eseguito some_commande lasciarlo consegnare direttamente il suo output. È più efficiente e anche più facile da leggere.


Quale implementazione / versione di tput/ nurses? Il mio (ncurses 6.0.20160625) fa il TIOCGWINSZ su stderr se non può farlo su stdout. cols=$(tput cols)o cols=$(tput cols 2<> /dev/ttyx) funziona bene.
Stéphane Chazelas,

@ StéphaneChazelas Ho 5.9 + 20140913-1 + b1 originariamente installato da Debian "sid". Sto solo cercando una versione più recente ora.
roaima,

1
Funziona anche con ncurses 5.7.20100313qui. Sei positivo cols=$(tput cols 2<> /dev/tty1)non funziona per te?
Stéphane Chazelas,

@ StéphaneChazelas affascinante. Hai ragione: se mi allontano stdout da un terminale, tput colsleggo da stderr . Ora ho bisogno di capire come riscrivere la mia risposta ...
roaima,

1
Userei stty size <"$terminal" | read rows columnsinvece di cercare di analizzarestty -a
Random832

13

tput colse tput linesinterroga la dimensione del terminale (dal driver del dispositivo terminale, non dal terminale stesso) dal dispositivo terminale sul suo stdout, e se stdout non è un dispositivo terminale come nel caso in cols=$(tput cols)cui si trova quindi una pipe, da stderr.

Quindi, per recuperare i valori da un dispositivo terminale arbitrario, è necessario aprire quel dispositivo sullo standard di tput:

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

(qui aperto in modalità di sola lettura, quindi tputnon genera i suoi messaggi di errore lì).

In alternativa, potresti essere in grado di utilizzare stty size. sttyinterroga il terminale su stdin:

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

Nessuno di questi è standard, quindi potrebbe (e in pratica non funzionerà) su tutti i sistemi. Tuttavia, dovrebbe essere abbastanza portabile su sistemi GNU / Linux.

A stty sizePOSIX è stata richiesta l'aggiunta di o un altro metodo per interrogare le dimensioni del terminale, ma la discussione non sembra andare da nessuna parte.


8

Questo script:

#!/bin/bash

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

Ha lavorato qui con assolutamente nulla di più .....

Perché stai impostando una variabile d'ambiente con i dati? COLONNE = $ (/ home / test / Documenti / get_columns.sh)

Stai cercando di ottenere colonne e righe da altri script o tty? È così? Ancora strano per me perché stai impostando la variabile d'ambiente delle colonne per lo script locale ....


Ciò non aiuta a recuperare i valori all'interno del cronlavoro dell'OP per un particolare terminale.
roaima,

1
Ahn? Che cosa? Ora sono più confuso, come possono gli script cronjobs avere larghezza ????? In realtà non funzionano in un terminale.
Luciano Andress Martini,

Lo so. Il cronlavoro richiede un terminale particolare per le sue caratteristiche. (Non sono del tutto sicuro del perché debba farlo, ma è quello che vuole l'OP.)
roaima,

@LucianoAndressMartini $ COLUMNS e $ LINES sono variabili bash, non funzionano (ad esempio) in trattino e posh
ingroxd

Tks. Lo so davvero, ma il mio script è hashbang con / bin / bash penso che dovresti sapere che dovresti usarlo. Se stai usando un unix senza bash, forse la mia risposta non è per te.
Luciano Andress Martini,

1

La mia risposta è diversa da quella di Roaima, poiché è dinamica. La sua risposta ti dà le dimensioni del terminale al momento della creazione. Se ad esempio stai usando un gestore di finestre di affiancamento, come i3 o bspwm, preferiresti avere la larghezza corrente del terminale. Quindi uso ssty dal pacchetto coreutils:

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

La soluzione di Luciano funziona perfettamente in xterm e xfce4-terminal. Non so se tutti i terminali impostano la variabile $ COLUMNS.


Questa non è più dinamica della mia risposta. Entrambi forniscono la dimensione del terminale nel punto in cui si eseguono i comandi.
roaima,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.