skalowalne okno konsoli szeregowej?

25

Podczas korzystania z konsoli szeregowej mojego systemu zawsze kończę na $COLUMNS=80i $LINES=24.

Chociaż mogę ręcznie zmienić te zmienne, jest to trochę denerwujące, gdy zmienia się okno terminala po stronie klienta.

Zwykle łączę się z konsolą za pomocą screen /dev/mytty baudrate.

Zmiana $TERMzmiennej środowiskowej na „screen” lub „xterm” nie pomaga.

Czy będę musiał zadzwonić gettyz niektórymi z nich zamiast vt100?

Nie trzeba dodawać, że wszystko to działa dobrze, gdy łączę się z tym samym komputerem za pomocą ssh.

Sven Geggus
źródło

Odpowiedzi:

26

Podobnie jak wspomniani wcześniej komentatorzy, nie ma alternatywy dla wywoływania resizepo każdym poleceniu, jeśli nie masz tego polecenia i nie chcesz instalować pakietu w miejscu ( xterm), oto dwa skrypty powłoki POSIX, które robią to samo za pomocą kodów specjalnych terminala ANSI:

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"
}

BTW, w moim .profilepliku znajdziesz: [ $(tty) = /dev/ttyS0 ] && res tak, że rozmiar terminala jest określany przy każdym logowaniu przez linię szeregową (tą, której używam do zarządzania), np. Po ponownym uruchomieniu urządzenia.
Zobacz także pomysł rsaw w komentarzach, aby [ $(tty) = /dev/ttyS0 ] && trap res2 DEBUGzamiast tego był tam wiersz, więc zmiana rozmiaru jest uruchamiana po każdym poleceniu (zauważ, że AFAIK nie jest lub nie zawsze jest możliwe busybox).

phk
źródło
3
PS: Aby uczynić bardziej trwałym, dodaj [[ $(tty) == /dev/ttyS0 ]] && trap res2 DEBUGdo jednej z konfiguracji profilu powłoki (np. /etc/profile, ~/.bash_profile). Spowoduje to, że będzie on uruchamiany po każdym pojedynczym poleceniu (co byłoby dobrze, jeśli zmieniasz rozmiar okien / paneli za pomocą screen / tmux / emulator terminala).
rsaw
2
Po użyciu go przez kilka minut, szybko zdałem sobie sprawę, że zarówno resi res2są zbyt powolne dla bynajmniej stosowania na pierwszego logowania. Na moich komputerach oba zajmują 0,5 sekundy, aby zakończyć ... sprawiając, że wszystkie moje polecenia wydają się powolne (gdy są używane z pułapką DEBUG). Ups! Nie mogę tego mieć. Chyba będę instalował xterm.
rsaw
3
@ phk xterm's resizejest znacznie szybszy - zwykle 0,002 s.
rsaw
1
@rsaw Oh OK, dobrze wiedzieć, myślałem, że będzie zachowywał się podobnie i dlatego będzie podobnie powolny. Pamiętam, że ta w niektórych przypadkach busyboxwydawała mi się równie powolna.
phk
1
Dzięki za to samodzielne rozwiązanie. Używam dystrybucji tylko do konsoli, która nie ma zainstalowanego x11 lub xterm, więc resizenie ma opcji.
thom_nic
16

Dla przypomnienia, oto odpowiedź na ten problem (wygrał Usenet):

Aplikacje działające wewnątrz konsoli wirtualnych aplikacji terminalowych ( xterm, rxvti przyjaciół) otrzymają SIGWINCHpo operacji doszło do zmiany rozmiaru. W ten sposób aplikacja będzie mogła przerysować okno itp. W odpowiednim module obsługi sygnału.

Niestety przy użyciu konsoli szeregowej nie ma takiego mechanizmu.

Możliwe jest jednak, że aplikacja będzie aktywnie pytać o bieżący rozmiar okna konsoli. Drugą najlepszą rzeczą jest zrobienie tego za każdym razem, gdy powłoka drukuje wiersz polecenia.

Można to osiągnąć najpierw poprzez skompilowanie specjalnego pliku wykonywalnego zmiany rozmiaru, a następnie użycie następujących poleceń bashrc:

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

Oczywiście nie zmieni to ustawień rozmiaru konsoli w aplikacji konsoli podczas działania.

Sven Geggus
źródło
1
Nie powinno być możliwe do uruchomienia protokołu w stosunku do linii szeregowej, które nie oferują wszystkie funkcje? Mam na myśli klienta i serwer. Mogą użyć wbudowanych sekwencji ucieczki, aby zrobić wszystko i nadal pracować z zwykłą konsolą tekstową!
Evi1M4chine
1
W rzeczywistości komentarz w kodzie jasno pokazuje, że nie jest to wersja resizezainstalowana w systemie.
Thomas Dickey,
9

Terminale „skalowalne” jako takie są wynikiem NAWS ( Negotiate About Window Sizez opcji rozmiaru okna Telnet RFC 1073 ).

Jeśli jesteś podłączony bezpośrednio do komputera za pomocą portu szeregowego, nie ma żadnych negocjacji, a komputer nie ma bezpośredniej wiedzy o wielkości ekranu twojego terminala.

Jeśli terminal może wynegocjować rozmiar, komputer wyśle SIGWINCHdo aplikacji działających w terminalu, informując go o zaktualizowaniu pojęcia rozmiaru ekranu.

Gdy komputer nie zna rozmiaru ekranu, zwykle ustawia rozmiar pokazany jako stty -a(wiersze i kolumny) na zero. Do użytku interaktywnego jest to trochę nieprzyjazne, a niektóre systemy używają zmiennych środowiskowych LINESi COLUMNSdo pomocy. Przypisane wartości mogą pochodzić z opisu terminala; częściej są po prostu zakodowane na stałe. Konwencja dla tych zmiennych wymaga, aby use_envzadziałały, chyba że zostaną wyraźnie wyłączone, np . W funkcji aplikacji curses . Z drugiej strony zmienne te mogą być przydatne, gdy nie są dostępne wiarygodne informacje. Z drugiej strony nie ma dogodnej metody zmiany tych zmiennych.

resizeProgramu (narzędzie wyposażony xterm) można użyć sekwencję wyjściową raporcie pozycji, kursor VT100-ustalania rozmiaru obrazu. Można to uruchomić z wiersza poleceń; (ponownie) nie ma dogodnego sposobu, aby to zrobić automatycznie. Jako efekt uboczny resizeaktualizuje informacje o wierszach / kolumnach wyświetlanych przez stty. Jego użycie do dostarczania zaktualizowanych zmiennych środowiskowych jest przydatne głównie w przypadkach takich jak ten, gdzie LINESi gdzie COLUMNS ustawione, i należy je zaktualizować.

Thomas Dickey
źródło
3

Oto inne rozwiązanie, które działało dla mnie świetnie na moim wbudowanym systemie Linux (Overo z uruchomioną Angstrom). Właśnie uruchomiłem go z mojego pliku .bashrc. Nie chciałem używać zmiany rozmiaru, ponieważ wymaga to instalacji niektórych pakietów X i nie chciałem tego.

Informowanie Raspberry Pi, że twój terminal jest większy niż 24 linie | Blog Shallow Thoughts

Austin Beer
źródło
3
Nie publikuj tylko linku:
podaj
1
Szkoda, że ​​potrzebuje Pythona.
Craig McQueen
1

Jeśli zamiast tego możesz użyć FreeBSD, dostępna jest komenda resizewin (1) , która robi dokładnie to, co chcesz.

Edward Tomasz Napierala
źródło
1

Podczas uruchamiania sesji powłoki przez linię szeregową wystarczy wywołać resizepolecenie wewnątrz tej sesji - po ustanowieniu połączenia i po każdej zmianie geometrii terminala.

resizeKomenda jest częścią xterm ale nie zależy na X11. Na przykład w Fedorze jest osobno pakowany jako xterm-resize.

Jak to działa: polecenie zmiany rozmiaru mierzy wysokość / szerokość za pomocą niektórych ruchów kursora, a następnie wysyła te wartości do terminala za pomocą sekwencji ucieczki.

W przypadku powłoki takiej jak zsh powoduje to również automatyczną aktualizację zmiennych LINESi COLUMNS(alternatywnie można ocenić instrukcje eksportu, które polecenia wypisują na standardowe wyjście).

Dlaczego jest to konieczne: w sesji lokalnej lub ssh terminal może zasygnalizować sesji zmiany geometrii (patrz SIGWINCH). Ten mechanizm nie działa przez połączenie szeregowe.

maxschlepzig
źródło
0

Oto prosta i szybka funkcja zmiany rozmiaru, która działa tylko w przypadku bash. Jest modyfikowany z wersji phk res2, wykorzystując bash, read -d delimaby uniknąć przekroczenia limitu czasu na zakończenie odczytu.

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