Größenveränderbares serielles Konsolenfenster?

25

Wenn ich die serielle Konsole meines Systems benutze, ende ich immer mit $COLUMNS=80und $LINES=24.

Obwohl ich diese Variablen manuell ändern kann, ist es etwas ärgerlich, dies jederzeit zu tun, wenn die Größe des clientseitigen Terminalfensters geändert wurde.

Normalerweise verbinde ich mich mit der Konsole screen /dev/mytty baudrate.

Das Ändern der $TERMUmgebungsvariablen auf "screen" oder "xterm" hilft nicht.

gettyMuss ich mit einigen von denen anrufen, anstatt mit vt100?

Es erübrigt sich zu erwähnen, dass all dies gut funktioniert, wenn ich mit ssh eine Verbindung zu demselben Computer herstelle.

Sven Geggus
quelle

Antworten:

26

Wie die Kommentatoren vor mir erwähnt haben, gibt es keine Alternative zum Aufrufen resizenach jedem Befehl. Wenn Sie diesen Befehl nicht haben und kein Paket installieren möchten, in dem es sich befindet ( xterm), sind hier zwei POSIX-Shell-Skripte, die dasselbe tun Verwenden von Escape-Codes für ANSI-Terminals:

res() {

  old=$(stty -g)
  stty raw -echo min 0 time 5

  printf '\0337\033[r\033[999;999H\033[6n\0338' > /dev/tty
  IFS='[;R' read -r _ rows cols _ < /dev/tty

  stty "$old"

  # echo "cols:$cols"
  # echo "rows:$rows"
  stty cols "$cols" rows "$rows"
}

res2() {

  old=$(stty -g)
  stty raw -echo min 0 time 5

  printf '\033[18t' > /dev/tty
  IFS=';t' read -r _ rows cols _ < /dev/tty

  stty "$old"

  # echo "cols:$cols"
  # echo "rows:$rows"
  stty cols "$cols" rows "$rows"
}

Übrigens, in meiner .profileDatei finden Sie Folgendes: [ $(tty) = /dev/ttyS0 ] && res Damit die Terminalgröße bei jedem Login über die serielle Leitung (die ich für die Verwaltung verwende) festgelegt wird, z. B. nach dem Neustart des Geräts.
Siehe auch die Idee von rsaw in den Kommentaren, die Zeile [ $(tty) = /dev/ttyS0 ] && trap res2 DEBUGstattdessen dort zu haben, damit die Größenänderung nach jedem Befehl ausgeführt wird (beachte, dass AFAIK es nicht oder nicht immer möglich ist busybox).

phk
quelle
3
PS: Um die Dauerhaftigkeit [[ $(tty) == /dev/ttyS0 ]] && trap res2 DEBUGzu erhöhen , fügen Sie eine der Shell-Profilkonfigurationen hinzu (z . B. /etc/profile, ~/.bash_profile). Dadurch wird es nach jedem einzelnen Befehl ausgeführt (was nur dann sinnvoll ist, wenn Sie die Größe von Fenstern / Fenstern mit screen / tmux / terminal-emulator ändern).
Rsaw
2
Nachdem es für ein paar Minuten mit merkte ich schnell , dass sowohl res& res2zu langsam sind und alles andere als den Einsatz auf der ersten Anmeldung. Auf meinen Rechnern dauert es beide 0,5 Sekunden, bis alle meine Befehle träge sind (wenn sie mit der DEBUG-Falle verwendet werden). Hoppla! Kann das nicht haben. Ich schätze, ich werde installieren xterm.
Rsaw
3
@phk xterm's resizeist schneller - normalerweise 0.002sec.
Rsaw
1
@rsaw Oh ok, gut zu wissen, ich dachte es würde sich ähnlich verhalten und daher ähnlich langsam sein. Ich erinnere mich, dass mir der eine in einigen busyboxgenauso langsam vorkam.
Phk
1
Vielen Dank für diese eigenständige Lösung. Ich verwende eine reine Konsolendistribution, auf der weder x11 noch xterm installiert sind. Daher resizeist dies keine Option.
thom_nic
16

Nur zur Veranschaulichung, hier ist die Antwort auf dieses Problem (das Usenet hat gewonnen):

Konsolenanwendungen in virtuellen Terminal - Anwendungen ausgeführt wird ( xterm, rxvtund Freunde) erhalten SIGWINCHnach einer Größenänderung stattgefunden hat. Auf diese Weise kann die Anwendung das Fenster usw. im entsprechenden Signalhandler neu zeichnen.

Leider gibt es bei Verwendung einer seriellen Konsole keinen solchen Mechanismus.

Es ist jedoch möglich, dass die Anwendung aktiv nach der aktuellen Fenstergröße der Konsole fragt . Das zweitbeste ist also, dies jedes Mal zu tun, wenn eine Eingabeaufforderung von der Shell gedruckt wird.

Dies kann erreicht werden, indem zuerst eine ausführbare Datei mit spezieller Größenänderung kompiliert und dann Folgendes verwendet wird bashrc:

if [ $(tty) == '/dev/ttyS0' ]; then
  trap resize DEBUG
fi

Dies ändert natürlich nicht die Einstellungen für die Konsolengröße in einer Konsolenanwendung zur Laufzeit.

Sven Geggus
quelle
1
Sollte es nicht möglich sein , ein Protokoll über die serielle Schnittstelle laufen, das nicht alle Funktionen anbieten? Ich meine, wir haben einen Client und einen Server. Sie könnten Inband-Escape-Sequenzen verwenden, um fast alles zu erledigen und trotzdem mit einer seriellen Klartext-Konsole arbeiten!
Evi1M4chine
1
Tatsächlich macht der Kommentar im Code deutlich, dass es sich nicht um die Version resizehandelt, die auf Ihrem System installiert ist.
Thomas Dickey
9

"Resizable" Terminals als solche sind ein Ergebnis von NAWS ( Negotiate About Window Sizevon RFC 1073 Telnet Window Size Option ).

Wenn Sie über einen seriellen Anschluss direkt mit dem Computer verbunden sind, ist keine Verhandlung erforderlich, und der Computer hat keine direkte Kenntnis über die Bildschirmgröße Ihres Terminals.

Wenn ein Terminal die Größe aushandeln kann, sendet der Computer SIGWINCHan Anwendungen, die im Terminal ausgeführt werden, und fordert sie auf, ihre Vorstellung von der Bildschirmgröße zu aktualisieren.

Wenn der Computer die Bildschirmgröße nicht kennt, setzt er die durch stty -a(Zeilen und Spalten) angegebene Größe normalerweise auf Null. Für die interaktive Verwendung ist dies etwas unfreundlich, und einige Systeme verwenden Umgebungsvariablen LINESund COLUMNS, um zu helfen. Die zugewiesenen Werte können aus der Klemmenbeschreibung abgeleitet werden; häufiger werden sie einfach hartcodiert. Die Konvention für diese Variablen verlangt, dass sie wirksam werden, sofern sie nicht ausdrücklich unterdrückt werden, z. B. in Fluchanwendungen use_env. Positiv zu vermerken ist, dass diese Variablen nützlich sein können, wenn keine zuverlässigen Informationen verfügbar sind. Auf der negativen Seite gibt es keine bequeme Methode zum Ändern dieser Variablen.

Das resizeProgramm (ein mitgeliefertes Dienstprogramm xterm) kann die Escape-Sequenz für Cursorpositionsberichte im VT100-Stil verwenden, um die Bildschirmgröße zu bestimmen. Dies kann über die Befehlszeile ausgeführt werden. Es gibt (wieder) keine bequeme Möglichkeit, dies automatisch zu tun. resizeAktualisiert als Nebeneffekt die Informationen zu Zeilen / Spalten, die von angezeigt werden stty. Sein Einsatz für aktualisierten Umgebungsvariablen Bereitstellung ist vor allem nützlich für Fälle wie diese, wo LINESund COLUMNS sind festgelegt und aktualisiert werden soll.

Thomas Dickey
quelle
3

Hier ist eine weitere Lösung, die auf meinem eingebetteten Linux-System (Overo mit Angstrom) hervorragend funktioniert hat. Ich habe es gerade aus meiner .bashrc-Datei ausgeführt. Ich wollte die Größenänderung nicht verwenden, da dazu einige X-Pakete installiert werden müssen, und das wollte ich nicht.

Sagen Sie Ihrem Raspberry Pi, dass Ihr Terminal größer als 24 Zeilen ist Shallow Thoughts Blog

Austin Beer
quelle
3
Bitte nicht nur schreiben Sie einen Link: sind das entsprechende Detail , so dass die Informationen auch hier zur Verfügung ...
jasonwryan
1
Schade, dass es Python braucht.
Craig McQueen
1

Falls Sie stattdessen FreeBSD verwenden könnten, gibt es den Befehl resizewin (1) , der genau das tut, was Sie wollen.

Edward Tomasz Napierala
quelle
1

Wenn Sie eine Shell-Sitzung über eine serielle Leitung ausführen, ist es ausreichend, den resizeBefehl innerhalb dieser Sitzung aufzurufen - nach dem Herstellen der Verbindung und nach jeder Änderung der Terminalgeometrie.

Der resizeBefehl ist Teil von xterm, hängt jedoch nicht von X11 ab. Zum Beispiel ist es auf Fedora separat verpackt als xterm-resize.

So funktioniert es: Der Befehl zum Ändern der Größe misst die Höhe / Breite über einige Cursorbewegungen und sendet diese Werte dann über Escape-Sequenzen an das Terminal.

Mit einer Shell wie zsh werden auch die Variablen LINESund automatisch aktualisiert COLUMNS(alternativ können die export-Anweisungen ausgewertet werden, die der Befehl an stdout ausgibt).

Warum dies notwendig ist: Mit einer lokalen oder ssh-Sitzung kann das Terminal die Sitzung über Geometrieänderungen informieren (vgl. SIGWINCH). Dieser Mechanismus funktioniert nicht über eine serielle Verbindung.

maxschlepzig
quelle
0

Hier ist eine einfache und schnelle Größenänderungsfunktion, die nur für Bash funktioniert. Es wurde von phk's res2 modifiziert, wobei bash verwendet wurde read -d delim, um zu vermeiden, dass das Timeout abgelaufen ist, um den Lesevorgang zu beenden.

resize() {
  old=$(stty -g)
  stty -echo
  printf '\033[18t'
  IFS=';' read -d t _ rows cols _
  stty "$old"
  stty cols "$cols" rows "$rows"
}
Gary Guo
quelle