Konsolenbreite mit einem Bash-Skript ermitteln

15

Ich stoße auf ein Problem, bei dem ich versuche, mithilfe von Skripten die Größe eines Terminals zu ermitteln. Normalerweise würde ich den Befehl tput colsin der Konsole verwenden, aber ich möchte in der Lage sein, diese Funktion durch strikte Verwendung von Skripten zu erreichen.

Ab sofort kann ich die laufende Konsole erkennen und deren Dateipfad ermitteln. Ich bemühe mich jedoch, diese Informationen zu verwenden, um die Breite der Konsole zu ermitteln. Ich habe versucht, den Befehl zu verwenden tput, aber ich bin ziemlich neu in Linux / Skripten, daher weiß ich nicht wirklich, was ich tun soll.

Der Grund dafür ist, dass ich in der Lage sein möchte, einen Cron- Eintrag einzurichten, der die Konsole von Zeit zu Zeit über seine Breite / Spalten benachrichtigt.

Das ist mein Code bisher:

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)

Die normale Ausgabe von TERMINAL& TERMINALPATHist und zum Beispiel &pts/terminalnumber/dev/pts/terminalnumberpts/0/dev/pts/0

sirgeezer21
quelle
1
Möglicherweise hilft Ihnen unix.stackexchange.com/questions/16578/… .
Phk
@phk Ich glaube nicht, dass das hilft. Das Problem dabei ist, wie der tty-Treiber über die tatsächlichen Werte für Spalten / Zeilen informiert wird. Hier ist es, sie vom tty-Treiber zu bestimmen.
Roaima
Ich hätte nicht gedacht, dass cronJobs Kontrollterminals haben.
TMN

Antworten:

17

Der tputBefehl ist ein ausgezeichnetes Werkzeug, kann jedoch leider nicht die tatsächlichen Einstellungen für ein beliebig ausgewähltes Terminal abrufen.

Der Grund dafür ist, dass es stdout für die Terminal-Eigenschaften liest und hier auch seine Antwort schreibt. In dem Moment, in dem Sie versuchen, die Ausgabe von zu erfassen tput cols, haben Sie auch die Informationsquelle entfernt.

Zum Glück sttyliest stdin anstelle von stdout, um die Eigenschaften des Terminals zu bestimmen. So können Sie die benötigten Größeninformationen abrufen:

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

Übrigens ist es unnötig umständlich, dies so zu schreiben echo $(/usr/bin/tput cols).

Für jedes Konstrukt führen echo $(some_command)Sie die some_commandAusgabe aus und erfassen sie, die Sie dann an echodie Ausgabe übergeben. In fast jeder Situation können Sie sich vorstellen, dass Sie genauso gut einfach ausgeführt haben some_commandund die Ausgabe direkt liefern lassen. Es ist effizienter und auch leichter zu lesen.

Roaima
quelle
Welche Implementierung / Version von tput/ nurses? Mine (ncurses 6.0.20160625) führt das TIOCGWINSZ auf stderr aus, wenn es auf stdout nicht möglich ist. cols=$(tput cols)oder cols=$(tput cols 2<> /dev/ttyx) funktioniert gut.
Stéphane Chazelas
@ StéphaneChazelas Ich habe 5.9 + 20140913-1 + b1 ursprünglich von Debian "sid" installiert. Ich suche gerade nach einer neueren Version.
Roaima
1
Funktioniert auch mit ncurses 5.7.20100313hier. Sind Sie sicher, cols=$(tput cols 2<> /dev/tty1)dass es bei Ihnen nicht funktioniert?
Stéphane Chazelas
@ StéphaneChazelas faszinierend. Sie haben Recht: Wenn ich stdout von einem Terminal entferne, tput colsliest stderr . Ich muss jetzt herausfinden, wie ich meine Antwort umschreiben kann ...
roaima
1
Ich würde verwenden, stty size <"$terminal" | read rows columnsanstatt zu versuchen, zu analysierenstty -a
Random832
13

tput colsund tput linesfragen Sie die Größe des Terminals (vom Terminalgerätetreiber, nicht vom Terminal selbst) vom Terminalgerät auf seiner Standardausgabe ab, und wenn die Standardausgabe kein Terminalgerät ist, wie im Fall, cols=$(tput cols)dass es sich dann um eine Pipe handelt, von stderr.

Um die Werte von einem beliebigen Endgerät abzurufen, müssen Sie dieses Gerät auf dem folgenden Verzeichnis öffnen tput:

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

(hier schreibgeschützt geöffnet, daher werden tputdort keine Fehlermeldungen ausgegeben).

Alternativ können Sie möglicherweise verwenden stty size. sttyfragt das Terminal nach stdin ab:

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

Keines davon ist Standard und funktioniert möglicherweise (und in der Praxis) nicht auf allen Systemen. Es sollte jedoch ziemlich portabel für GNU / Linux-Systeme sein.

Das Hinzufügen stty sizeoder eine andere Methode zum Abfragen der Terminalgröße wurde an POSIX angefordert, aber die Diskussion scheint nirgendwo hin zu führen.

Stéphane Chazelas
quelle
8

Dieses Skript:

#!/bin/bash

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

Hier hat mit absolut nix mehr gearbeitet .....

Warum setzen Sie eine Umgebungsvariable mit Daten? COLUMNS = $ (/ home / test / Documents / get_columns.sh)

Versuchen Sie, die Spalten und Zeilen aus einem anderen Skript oder tty abzurufen? Ist es das? Für mich immer noch seltsam, weil Sie die Umgebungsvariable columns für das lokale Skript festlegen ....

Luciano Andress Martini
quelle
Dies hilft nicht, die Werte innerhalb des OP- cronAuftrags für ein bestimmtes Terminal abzurufen .
Roaima
1
Ahn? Was? Jetzt bin ich mehr verwirrt, wie können Cronjobskripte Breite haben ????? Sie laufen eigentlich nicht in einem Terminal.
Luciano Andress Martini
Ich kenne. Der cronJob fragt ein bestimmtes Terminal nach seinen Eigenschaften ab. (Ich bin nicht ganz sicher, warum es das tun muss, aber das ist, was die OP will.)
Roaima
@LucianoAndressMartini $ COLUMNS und $ LINES sind bash Variablen, es funktioniert nicht (zum Beispiel) in Schuss und vornehm
ingroxd
Tks. Ich weiß es wirklich, aber mein Skript ist Hashbang mit / bin / bash. Ich denke, es soll Ihnen klar sein, dass Sie es verwenden sollten. Wenn Sie Unix ohne Bash verwenden, ist meine Antwort möglicherweise nicht für Sie.
Luciano Andress Martini
0

Meine Antwort ist anders als die von Roaima, da sie dynamisch ist. Seine / Ihre Antwort gibt Ihnen die Größe des Terminals bei der Erstellung. Wenn Sie beispielsweise einen Kachelfenster-Manager wie i3 oder bspwm verwenden, möchten Sie lieber die aktuelle Breite des Terminals haben. Also benutze ich ssty aus dem Paket coreutils:

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

Lucianos Lösung funktioniert einwandfrei in xterm und xfce4-terminal. Ich weiß nicht, ob alle Terminals die Variable $ COLUMNS setzen.

Sasha
quelle
Das ist nicht dynamischer als meine Antwort. Beide geben die Terminalgröße an dem Punkt an, an dem Sie die Befehle ausführen.
Roaima