изменить размер окна последовательной консоли?

25

При использовании последовательной консоли моей системы я всегда получаю $COLUMNS=80и $LINES=24.

Хотя я могу изменить эти переменные вручную, это несколько раздражает, когда я изменяю размер окна терминала на стороне клиента.

Обычно я подключаюсь к консоли используя screen /dev/mytty baudrate.

Изменение $TERMпеременной среды на «screen» или «xterm» не помогает.

Нужно ли мне звонить gettyс некоторыми из них вместо vt100?

Само собой разумеется, что все это прекрасно работает, когда я подключаюсь к той же машине, используя ssh.

Свен Геггус
источник

Ответы:

26

Как и упомянутые выше комментаторы, нет альтернативы вызову resizeпосле каждой команды, если у вас нет этой команды и вы не хотите устанавливать пакет, в котором она находится ( xterm), вот два сценария оболочки POSIX, которые делают то же самое используя коды выхода терминала 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"
}

Кстати, в моем .profileфайле вы найдете следующее: [ $(tty) = /dev/ttyS0 ] && res так, чтобы размер терминала определялся при каждом входе в систему через последовательную линию (тот, который я использую для управления), например, после перезагрузки устройства.
См. Также идею rsaw в комментариях, чтобы [ $(tty) = /dev/ttyS0 ] && trap res2 DEBUGвместо этого была строка, чтобы изменение размера выполнялось после каждой команды (обратите внимание, что AFAIK это не всегда или не всегда возможно, busyboxхотя).

PHK
источник
3
PS: Для того, чтобы сделать более постоянным, добавьте [[ $(tty) == /dev/ttyS0 ]] && trap res2 DEBUGк одному из конфигов профиля оболочки (например, /etc/profile, ~/.bash_profile). Это заставит его запускаться после каждой отдельной команды (что было бы хорошо, если вы изменяете размеры окон / панелей с помощью screen / tmux / Terminal-Emulator).
Rsaw
2
После использования его в течение нескольких минут , я быстро понял , что оба resи res2являются слишком медленными для чего , кроме использования на первом входе в систему. На моих машинах они оба требуют 0,5 секунды, чтобы закончить ... заставляя все мои команды казаться вялыми (при использовании с ловушкой DEBUG). Упс! Не может этого иметь. Думаю, я буду устанавливать xterm.
Rsaw
3
@phk xterm resizeбыстрее, чем обычно - 0,002 сек.
Rsaw
1
@rsaw О, хорошо, приятно знать, я думал, что он будет вести себя одинаково и поэтому будет таким же медленным. Я помню, что один из них busyboxказался мне таким же медленным.
phk
1
Спасибо за это автономное решение. Я использую только консольный дистрибутив, на котором не установлены x11 или xterm, поэтому resizeэто не вариант.
thom_nic
16

Для справки, вот ответ на эту проблему (Usenet победил):

Консольные приложения , работающие в виртуальных терминальных приложений ( xterm, rxvtи друзей) будет получать SIGWINCHпосле того, как операция изменения размера имеет место. Таким образом, приложение сможет перерисовать окно и т. Д. В соответствующем обработчике сигналов.

К сожалению, при использовании последовательной консоли такой механизм отсутствует.

Однако приложение может активно запрашивать текущий размер окна консоли. Итак, вторая лучшая вещь - делать это каждый раз, когда командная строка печатается оболочкой.

Это может быть достигнуто путем компиляции специального исполняемого файла изменения размера, а затем с помощью следующего в bashrc:

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

Конечно, это не изменит настройки размера консоли в консольном приложении во время выполнения.

Свен Геггус
источник
1
Не должно быть возможным запустить протокол по последовательной линии, что делает предлагают все возможности? Я имею в виду, у нас есть клиент и сервер. Они могут использовать встроенные escape-последовательности, чтобы делать практически все, и при этом работать с обычной текстовой последовательной консолью!
Evi1M4chine
1
На самом деле, комментарий в коде дает понять, что это не та версия, resizeкоторая установлена ​​в вашей системе.
Томас Дики
9

Терминалы «изменяемого размера» как таковые являются результатом NAWS ( Negotiate About Window Sizeиз RFC 1073 Опция размера окна Telnet ).

Если вы подключены напрямую к компьютеру через последовательный порт, согласование не требуется, и компьютер не знает напрямую о размере экрана вашего терминала.

Если терминал может согласовать размер, компьютер отправит SIGWINCHприложениям, работающим в терминале, указание им обновить свое представление о размере экрана.

Когда компьютер не знает размера экрана, он обычно устанавливает размер, показанный stty -a(строки и столбцы), равным нулю. Для интерактивного использования это немного недружелюбно, и некоторые системы используют переменные окружения LINESи COLUMNSдля помощи. Присвоенные значения могут быть получены из описания терминала; чаще они просто жестко закодированы. Соглашение для этих переменных требует, чтобы они вступили в силу, если они явно не подавлены, например, в use_envфункции приложения curses . С положительной стороны, эти переменные могут быть полезны, когда нет надежной информации. С другой стороны, нет удобного метода для изменения этих переменных.

resizeПрограмма (утилита снабжена xterm) можно использовать VT100-стиль отчета позиции курсора последовательность для определения размера экрана. Это может быть запущено из командной строки; (опять же) нет удобного способа сделать это автоматически. Как побочный эффект, resizeобновляет информацию о строках / столбцах, видимых stty. Его использование для обеспечения обновленных переменных сред в основном полезно для таких случаев, как это, где LINESи COLUMNS будет установлены, и должны быть обновлены.

Томас Дики
источник
3

Вот еще одно решение, которое отлично сработало для меня в моей встроенной Linux-системе (Overo под управлением Angstrom). Я просто запустил его из моего файла .bashrc. Я не хотел использовать изменение размера, потому что это требует установки некоторых пакетов X, и я не хотел этого.

Сообщаем вашему Raspberry Pi, что ваш терминал больше 24 линий | Мелкий Мысли Блог

Остин Пиво
источник
3
Пожалуйста, не просто
публикуйте
1
Жаль, что нужен Python.
Крейг МакКуин
1

Если вы могли бы использовать FreeBSD вместо этого, есть команда resizewin (1) , которая делает именно то, что вы хотите.

Эдвард Томаш Напирала
источник
1

При запуске сеанса оболочки по последовательной линии достаточно вызвать resizeкоманду внутри этого сеанса - после установления соединения и после каждого изменения геометрии терминала.

Команда resizeявляется частью xterm, но не зависит от X11. Например, на Fedora он отдельно упакован как xterm-resize.

Как это работает: команда resize измеряет высоту / ширину с помощью некоторых движений курсора, а затем отправляет эти значения в терминал с помощью escape-последовательностей.

С оболочкой , как ЗШ это также автоматически обновляет LINESи COLUMNSпеременные ( в качестве альтернативы, можно оценить экспортные заявления команд печатают на стандартный вывод).

Почему это необходимо: при локальном сеансе или сеансе ssh терминал может сигнализировать сеансу об изменениях геометрии (см. SIGWINCH). Этот механизм не работает через последовательное соединение.

maxschlepzig
источник
0

Вот простая и быстрая функция изменения размера, которая работает только для bash. Он модифицирован из res2 команды phk и использует bash, read -d delimчтобы не дать тайм-ауту закончить чтение.

resize() {
  old=$(stty -g)
  stty -echo
  printf '\033[18t'
  IFS=';' read -d t _ rows cols _
  stty "$old"
  stty cols "$cols" rows "$rows"
}
Гэри Го
источник