Установить размер консоли c linux
23 сен 2016, 00:11
Здравствуйте, форумчане!У меня ноутбук, экран около 16 дюймов, помимо встроенной видеокарты intel установлена nvidia GeForce GTX 970M. Разрешение по умолчанию 3840х2160. Поскольку монитор небольшой, установил более низкое разрешение 1360x768 в Х. Чтобы экран входа в систему имел такое разрешение, прописал его явно в xorg.conf (помогло). Однако шрифт консоли (Alt+Ctrl+Fx) очень-очень мелкий (наверное, разрешение по умолчанию). Чтобы хоть что-нибудь можно было прочитать установил самый крупный шрифт через console-setup: 16x32 (только фрейм-буфер). Теперь по крайней мере можно разобрать текст. Пытался через /etc/default/grub изменить разрешение консоли. Безуспешно. Прошу всех неравнодушных откликнуться! :'(
ОС - Линукс Минт 18 (Синамон).
Итак, дело сделано.
Для начала нужно создать скрипт /etc/initramfs-tools/hooks/edid :
Затем надо перегенерировать образ initramfs, для этого есть команда: После этого прописать параметр загрузки в /etc/default/grub :И перезагрузиться. Если всё сработает, то те же настройки применятся не только к консоли, но и к Иксам.
Ну и под конец можно убрать параметр загрузки в конфиге GRUB, чтобы не мешался (туда прописывали для теста), и передавать параметр модулю напрямую, прописав в /etc/modprobe.d/drm-kms-helper.conf :
23 сен 2016, 01:18
burnside ,
Если я верно понял вопрос - то привести tty и иксы к нужному разрешению можно следующим образом:
Для начала, на этапе отображения меню grub жмем клавишу с чтоб попасть в его консоль, там набираем vbeinfo и видим все доступные разрешения экрана. Запоминаем нужное и бутимся в систему
По факту загрузки - добавляем эти строчки в /etc/default/grub, в моём примере 1280х960:
Именно nomodeset не даст сползти разрешению в дальнейшем
Затем даём sudo update-grub и перезагружаемся.
23 сен 2016, 07:11
Chocobo , спасибо за развернутый ответ! Такие манипуляции я уже проделывал ранее. Из всех доступных разрешений формата 16x9 vbeinfo выдает только 3840х2160. Если поставить любое другое разрешение из vbeinfo (например, 1024x768), то после этого графическая оболочка загружается только в безопасном режиме. Приходится возвращать настройки grub в исходное состояние. Напомню, что мое рабочее разрешение (в виду небольшого размера монитора ноутбука) 1360x768 (можно и 1920x1080, но уже менее комфортно). Эх, требуется какой-то иной подход.23 сен 2016, 08:24
Если мыслить "правильно", то надо не разрешение экрана менять, а использовать DE и приложения, поддерживающие HiDPI. Например, GNOME 3, KDE 5, Cinnamon, MATE (но в нём пока не полная поддержка) и просто приложения, использующие GTK 3 и Qt 5. Суть в том, что элементы управления и шрифты будут увеличены в несколько раз (обычно ровно в два раза).
Менять разрешение в консоли уж точно не стоит. Нужно просто сменить шрифт, вот и всё. Сделать это можно командой:
Как шрифт выбрать, например, Terminus, а размер установить в максимум. Остальные параметры лучше не трогать. После этого, возможно, потребуется перезагрузиться, чтобы увидеть результат.
UPD: прошу прощения, не заметил, что про console-setup говорилось в первом посте.
В таком случае можно последовать инструкциям отсюда . Там можно увидеть, что для не-дефолтных разрешений (список приведён) надо создавать свой EDID-файл. Параметр загрузки nomodeset при этом не должен быть выставлен.
Как узнать размер терминала?
Т.е. количество строчек и длину строки?
Желательно стандартными средствами без использования библиотек ncurses и подобных.
вообще поидее нужно что то типа
struct winsize wins;
err = ioctl(fd, TIOCGWINSZ, &wins);
/* TODO: err check here */
printf("cols=%d rows=%d\n", wins.ws_col, wins.ws_row);
> err = ioctl(fd, TIOCGWINSZ, &wins);
А если терминал -- не локальный, а подключен через RS232C?
> какая разница? :)
Работать не будет.
Причем необязательно через RS232C -- вообще на любом терминале, кроме локальной консоли linux.
Подумай: ioctl'ы обрабатываются ядром. Как о них узнает терминал (или его эмулятор -- xterm, например). Никак. Поэтому и работать такой способ будет только на локальной linux-консоли. То есть на мониторе, подключенном к видеоадаптеру данной машины, и только в том случае, если выводом управляет ядро, а не X Windiw, или Midnight Commander, или какая другая прога, запустившая данную программу на псевдотерминале.
какой-то у тебя бессвязный поток сознания. :)
1) ioctl передается драйверу терминала. Можешь сам поглядеть в linux/drivers/char/vt.c
2) это как еще xterm в обход ядра ходит? Вы что-то путаете, батенька
> ioctl передается драйверу терминала.
И что? Драйверу _какого_ терминала передается? Драйверу виртуальной консоли linux. Я и не спорю, что на локальной linux-консоли ioctl'ы будут работать. Ты, наверно, не в курсе, что, кроме виртуальных linux-консолей, существуют другие терминалы? Так вот, они существуют. И к linux'у не имеют никакого отношения. Если ты зашел по сети на linux-сервер, куда пойдет твой ioctl? Удаленному хосту? Даже и не надейся на это. Драйверу vt сервера? Ну подумай, как он тебе узнает размеры экрана удаленного хоста?
> это как еще xterm в обход ядра ходит?
В исходники его погляди -- увидишь как. Для вывода xterm использует запрос ImageText8 X сервера (не напрямую, а черех Xlib, но это сути не меняет). X сервер делает видеовывод собственными средствами, не используя для этого графические возможности ядра (у которого их нет).
Ну напиши ты простую программу, которая делает какой-нибудь ioctl на STDOUT_FILENO. Запусти ее на виртуальной консоли linux. Убедись, что она работает (под mc не пытайся -- не заработает). Запусти X Window. Открой окно xterm. Запусти в нем эту же прогу. Убедись, что она _не_ работает (также как и под mc). Почему? Да потому что ее stdout'ом будет не /dev/ttyN, а /dev/pts/N (где N -- какое-то число). Если уж ты способен читать исходники ядра, то погляди, какие ioctl'ы поддерживает псевдотерминал (/usr/src/linux/drivers/char/pty.c).
ЗЫ: если еще раз заявишь про бессвязный поток сознания -- ответа не получишь (мне не платят за ответы на твои вопросы, а хамства мне и в реале хватает).
уважаемый nobody давайте сделаем проще. размер терминала можно узнать командой stty -a запускаем в консоли и в xterm команду strace -olog stty -a внимательно смотрим в файл log и видим (о чудо!) что размер терминала в том и другом случае вернулся через ioctl TIOCGWINSZ, который отработал нормально. Я это проделал, а вы можете мне поверить на слово если такой занятой человек :)
То, что там иксы повесили на master side pty, и какими средствами они организуют вывод в данном случае никакой роли не играет - все равно все пройдет через драйвер терминала в ядре.
С Уважением SadStork
Ok, насчет программного терминала ты оказался прав (щелчок мне по носу). Одна программа вызывает ioctl для установки переменной "размеры_терминала", другая вызовом ioctl может считать эту переменную. В случае vt инициализирует эту переменную драйвер linux-консоли, в случае pts -- программа на стороне master.
А как насчет аппаратного терминала? Ведь он не сможет установить эту переменную. Чтобы этот способ работал, должна быть какая-то программа на данной машине, которая знает размеры экрана подключенного терминала и может установить переменную ядра соответствующим образом.
Способ, основанный на кодах управления терминалом (приведенный мной выше) будет работать на любом терминале, потому что эти коды интерпретируются самим терминалом.
что-то я вас не понимаю - для того, чтобы слать по линии инициализационные данные о размерах терминала нужна программа, а чтобы ловить esc-последовательности которые интерпретируются "самим терминалом" никакой программы не требуюется? :) Там Святой Дух их перехватывает и интерпретирует, видимо.
Извините за сарказм
Дело в том, что ни один терминал не умеет "слать по линии инициализационные данные о размерах терминала". Зато любой совместимый по кодам с vt100 умеет интерпретировать их.
Простой пример. Захожу из дома по модему на рабочую машину. Делаю stty -a. Мне сообщается, что размер терминала = 0 строк и 0 столбцов.
Что делать? Альтернатив тут всего 3:
1) Юзать ncurses (эта либа использует базу данных terminfo для получения информации о терминале, в т.ч. о его размерах).
2) Парсить terminfo вручную.
3) Юзать коды управления терминалом.
int get_term_size(int *width, int *height)
<
setvbuf(stdout, NULL, _IONBF, 0);
fputs("\x1B[255;255H\x1B[6n", stdout);
return scanf("\x1B[%d;%dR", height, width) == 2;
>
Реально же будет всего 2 строки, потому что функция setvbuf будет вызвана еще раньше: если программеру нужны размеры экрана, значит он собирается работать в полноэкранном режиме, а значит построчная буферизация stdout должна быть отключена.
вообще говоря это недореализация в linux - по идеи все терминальные девайсы(такие как виртуальный, псевдо и сериальный терминалы) должны иметь одинаковый базовый ioctl(как во FreeBSD например) .. вообще говоря у тебя терминал может и не быть vt100 компатабельным и ты все равно не зная ньюансов сможешь узнать размер через TIOCGWINSZ .. так что все зависит от того что надо в конце концов получить ..
в твоем случае ты должен быть уверен что терминал заинтерпретирует тебя корректно, если этого не произойдет то может возникнуть десинхронизация .. в случае с ioctl ты должен быть уверен что дескриптор засосациирован(на самом деле не должен просто можешь получить левые данные) с дерминальным тевайсом
>1) Юзать ncurses (эта либа использует базу данных
>terminfo для получения информации о терминале, в т.ч. о
>его размерах).
>2) Парсить terminfo вручную.
помоему для получения terminfo используется ioctl
> все терминальные девайсы(такие как виртуальный,
> псевдо и сериальный терминалы) должны
> иметь одинаковый базовый ioctl
Непонятно, что ты имеешь в виду под словом `ioctl' применительно к аппаратному терминалу? ioctl -- это системный вызов. Прога из юзерспэйса делает на своей машине int 80h (для linux@PC). Ядро ОС этой же самой машины этот вызов обрабатывает. Дальше этой машины ioctl не уходит. Системные вызова не передаются по кабелям (будь то сетевой кабель или RS232C). Каким образом терминал, подключенный через кабель, узнает о каком-то там ioctl?
Может быть, ты имеешь в виду следующее: ядро, обнаружив на линии терминал, посылает ему Esc-последовательность для получения его размеров и прочей инфы? А потом проги на этой машине могут обращаться по ioctl к ядру для получения этой инфы, так? Если я правильно угадал, то объясни, как ядро может обнаружить подключение терминала? Ведь по RS232C может подключаться все, что угодно. И посылаемые подключенному девайсу коды могут сделать с ним что-то, что юзеру не надо. И потом, зачем все это? Есть база данных terminfo, в которой все существующие терминалы описаны. А если прога не хочет (или не может) юзать terminfo, то пускай и посылает сама Esc-коды терминалу. Зачем ядру эти заморочки?
> в твоем случае ты должен быть уверен
> что терминал заинтерпретирует тебя корректно
Ты обратил внимание на последнюю строку функции?
return scanf("\x1B[%d;%dR", height, width) == 2;
Если терминал не поддерживает Esc-коды vt100 (а точнее, ECMA-48 CSI sequences), то функция возвратит 0. В этом случае размеры терминала останутся неизвестными. Ну и что? Если Esc-последовательности не поддерживаются, ты все равно не сможешь работать в полноэкранном режиме (как ты собираешься без них устанавливать курсор в произвольную позицию экрана?).
> помоему для получения terminfo используется ioctl
Неа, обычная юзерспэйсная база данных. В ядре она нафиг не нужна. Хранится на диске. У меня это каталог /usr/share/terminfo. Идет вместе с ncurses (в том же архиве). Устанавливается также вместе с ncurses (по make install).
Кстати, у юзера вполне может оказаться /etc/termcap вместо terminfo. Если не ошибаюсь, на фряхе используется именно он. Его парсить еще веселее -- это очень большой текстовый файл. БД terminfo была придумана для замены /etc/termcap (она бинарная, и каждый файл содержит описание только одного терминала, а значит с ней быстрее работать).
> Непонятно, что ты имеешь в виду под словом `ioctl' применительно к
> аппаратному терминалу?
ну батенька .. апаратные терминалы к линуксу вообще отношения не имеют
и я про них ни словом не обмолвился .. а под сериальным терминалом
имелся ввиду псевдо девайс(чарактер девайс) который может слушаться и
обрабатываться каким нибудь getty например при попадании данных в
линию RS232 .. после этого getty устанавливает запрашиваемые размеры
(например по получении соотв ESC-последовательноти) и ты можешь
пользоваться ioctl(на стороне getty) для получения установленных
размеров (то есть получился твой апаратный терминал - это коробка с
линуском и с торчащим RS232 нульмодемом).
> Ты обратил внимание на последнюю строку функции?
> return scanf("\x1B[%d;%dR", height, width) == 2;
обратил .. именно из-за этой последней строчки и может возникнуть
десинхронизация .. например имеем терминал не vt100 компатабельный -
ты послал ему эту ESC-посл для получения размера и висишь в scanfе
ждешь ответа, но он(терминал) не поддерживает эту посл и в этот момент
решил послать тебе какие-то данные - соответсвенно если во время
работы с терминалом ты проделаешь подобное то ты потеряешь эти данные
в отсосанном(вернувшем 0) scanf вызове.
> Неа, обычная юзерспэйсная база данных. В ядре она нафиг не
> нужна. Хранится на диске. У меня это каталог
> /usr/share/terminfo. Идет вместе с ncurses (в том же
> архиве). Устанавли вается также вместе с ncurses (по make install).
а - ну пожалуйста что там получается .. у любого терминала описаного в
terminfo должен быть заранее оговоренный размер? - тухлость.
вобщем не хочу тебя ни в чем убеждать - пользовать
ESC-последовательности в соответствующих местах катируется.
> ioctl -- это системный вызов. Прога из
> юзерспэйса делает на своей машине int 80h (для linux@PC). Ядро ОС
> этой же самой машины этот вызов обрабатывает. Дальше этой машины
> ioctl не уходит. Системные вызова не передаются по кабелям (будь то
> сетевой кабель или RS232C). Каким образом терминал, подключенный
> через кабель, узнает о каком-то там ioctl?
:))) прикинь системные вызовы да даже аппаратные прерывания могу
передаваться по кабелям. Кстати если системный вызовы не могут
передаваться через кабеля - то как работает клиентская часть NFS, а
точнее ее RPC часть?
> как работает клиентская часть NFS, а точнее ее RPC часть?
А как работает запрос файла у FTP сервера? Сервер делает open, read и close. То есть как минимум 3 сискола. Ты готов считать запрос файла передачей сисколов по сети?
Я вообще-то понимаю, о чем ты говоришь: с точки зрения клиента происходит следующее: приложение обратилось к ядру, а ядро полезло в сеть. По ведь ядро не передает в сеть именно _сискол_. Это просто невозможно -- сеть же может быть гетерогенной. Представь: я в вызове open указываю права доступа 755, а сервер работает на Windows. Если считать это именно передачей сискола, то должно быть так: ядро Windows получает от ядра linux сискол open. Опаньки -- нет такого сискола. Есть CreateFile -- ладно, вызываем его. Но с какими аргументами?
Понимаешь, это не есть передача сискола. Это просто запрос обслуживания по сети. А то что с точки зрения программы-клиента какой-то локальный сискол привел к сетевой активности -- ну и что? Когда ты обращаешься к FTP серверу, ты делаешь сискол send, в результате которого на сервере происходит сискол read (или ReadFile, или что-то еще). Та же сетевая активность, только вид сбоку.
> аппаратные прерывания могу передаваться по кабелям.
Ты говоришь об экзотических архитектурах, где несколько машин, связанных сетью, образуют одну большую машину, или что-то типа того? Если да, то в этом случае сеть -- уже не сеть, а разновидность системной шины. Я понимаю: шина -- она, конечно, тоже провода (даже шина данных персоналки), но я все-таки не имел ее в виду. Когда я говорил про кабеля, то имел в виду связь отдельных устройств, не представляющих собой в связанном виде единое целое с общей шиной данных/адреса/управления/чего-то-еще.
функции можно вызывать по сети .. see RPC(Remote Procedure Call) .. во многих ядрах есть kern-rpc. Hа самом деле представь себе картину - все девайсы имеют Ethernet как системную шину .. в том числе и биос и память и винт и все что угодно :)) - или например с помощью FireWire ты _хардверно_ можешь замапить себе чужую память и работать с ней как со своей собственной .. а что если именно в этом куске памяти расположить новый сискол(например насильно запихнуть модуль(который содержит новый сискол) в этот участок памяти)?
При использовании последовательной консоли моей системы я всегда получаю $COLUMNS=80 и $LINES=24 .
Хотя я могу изменить эти переменные вручную, это несколько раздражает, когда я изменяю размер окна терминала на стороне клиента.
Обычно я подключаюсь к консоли используя screen /dev/mytty baudrate .
Изменение $TERM переменной среды на «screen» или «xterm» не помогает.
Нужно ли мне звонить getty с некоторыми из них вместо vt100?
Само собой разумеется, что все это прекрасно работает, когда я подключаюсь к той же машине, используя ssh.
Как и упомянутые выше комментаторы, нет альтернативы вызову resize после каждой команды, если у вас нет этой команды и вы не хотите устанавливать пакет, в котором она находится ( xterm ), вот два сценария оболочки POSIX, которые делают то же самое используя коды выхода терминала ANSI:
- Положение курсора сохранено ( \0337 , DECSC ).
- Курсоры перемещаются в максимально правую нижнюю точку ( \033[r\033[999;999H , DECSTBM ? + CUP ).
- Положение курсора сообщается ( \033[6n , DSR ).
- Курсор перемещается обратно в ранее сохраненную позицию ( \0338 , DECRC ).
Кстати, в моем .profile файле вы найдете следующее: [ $(tty) = /dev/ttyS0 ] && res так, чтобы размер терминала определялся при каждом входе в систему через последовательную линию (тот, который я использую для управления), например, после перезагрузки устройства.
См. Также идею rsaw в комментариях, чтобы [ $(tty) = /dev/ttyS0 ] && trap res2 DEBUG вместо этого была строка, чтобы изменение размера выполнялось после каждой команды (обратите внимание, что AFAIK это не всегда или не всегда возможно, busybox хотя).
/.bash_profile ). Это заставит его запускаться после каждой отдельной команды (что было бы хорошо, если вы изменяете размеры окон / панелей с помощью screen / tmux / Terminal-Emulator).
После использования его в течение нескольких минут , я быстро понял , что оба res и res2 являются слишком медленными для чего , кроме использования на первом входе в систему. На моих машинах они оба требуют 0,5 секунды, чтобы закончить . заставляя все мои команды казаться вялыми (при использовании с ловушкой DEBUG). Упс! Не может этого иметь. Думаю, я буду устанавливать xterm . @rsaw О, хорошо, приятно знать, я думал, что он будет вести себя одинаково и поэтому будет таким же медленным. Я помню, что один из них busybox казался мне таким же медленным. Спасибо за это автономное решение. Я использую только консольный дистрибутив, на котором не установлены x11 или xterm, поэтому resize это не вариант.Для справки, вот ответ на эту проблему (Usenet победил):
Консольные приложения , работающие в виртуальных терминальных приложений ( xterm , rxvt и друзей) будет получать SIGWINCH после того, как операция изменения размера имеет место. Таким образом, приложение сможет перерисовать окно и т. Д. В соответствующем обработчике сигналов.
К сожалению, при использовании последовательной консоли такой механизм отсутствует.
Однако приложение может активно запрашивать текущий размер окна консоли. Итак, вторая лучшая вещь - делать это каждый раз, когда командная строка печатается оболочкой.
Это может быть достигнуто путем компиляции специального исполняемого файла изменения размера, а затем с помощью следующего в bashrc :
Конечно, это не изменит настройки размера консоли в консольном приложении во время выполнения.
Не должно быть возможным запустить протокол по последовательной линии, что делает предлагают все возможности? Я имею в виду, у нас есть клиент и сервер. Они могут использовать встроенные escape-последовательности, чтобы делать практически все, и при этом работать с обычной текстовой последовательной консолью! На самом деле, комментарий в коде дает понять, что это не та версия, resize которая установлена в вашей системе.Терминалы «изменяемого размера» как таковые являются результатом NAWS ( Negotiate About Window Size из RFC 1073 Опция размера окна Telnet ).
Если вы подключены напрямую к компьютеру через последовательный порт, согласование не требуется, и компьютер не знает напрямую о размере экрана вашего терминала.
Если терминал может согласовать размер, компьютер отправит SIGWINCH приложениям, работающим в терминале, указание им обновить свое представление о размере экрана.
Когда компьютер не знает размера экрана, он обычно устанавливает размер, показанный stty -a (строки и столбцы), равным нулю. Для интерактивного использования это немного недружелюбно, и некоторые системы используют переменные окружения LINES и COLUMNS для помощи. Присвоенные значения могут быть получены из описания терминала; чаще они просто жестко закодированы. Соглашение для этих переменных требует, чтобы они вступили в силу, если они явно не подавлены, например, в use_env функции приложения curses . С положительной стороны, эти переменные могут быть полезны, когда нет надежной информации. С другой стороны, нет удобного метода для изменения этих переменных.
resize Программа (утилита снабжена xterm ) можно использовать VT100-стиль отчета позиции курсора последовательность для определения размера экрана. Это может быть запущено из командной строки; (опять же) нет удобного способа сделать это автоматически. Как побочный эффект, resize обновляет информацию о строках / столбцах, видимых stty . Его использование для обеспечения обновленных переменных сред в основном полезно для таких случаев, как это, где LINES и COLUMNS будет установлены, и должны быть обновлены.
Здравствуйте. Захотел написать консольную игрушку на С++. Первым делом решил установить размеры окна консоли. Google сразу пришел на помощь, но проблема в том что все рецепты используют библиотеку windows.h, а на моей машине стоит Ubuntu 16.04. Буду признателен за помощь.
Ответы (1 шт):
К счастью, еще разработчики xterm, наряду с реализацией огромного количества управляющих последовательностей (Control Sequences) типичных для распространенных текстовых терминалов (управление курсором, цветом, набором символов, вставкой, удалением и сдвигом текста и т.д. и т.п.), подумали об аналогичных последовательностях для перемещения окна эмулятора и изменении его размера на экране оконной системы X-windows (в приведенной выше ссылке их можно найти поиском по тексту Window manipulation).
Для изменения размера окна в символах используется последовательность:
ESC [ 8; height; width; t
Где ESC -- это символ с кодом 033 (восьмеричный) 27 (десятичный) или "\e" в строке.
Вообще, в том же документе для последовательность символов ESC [ используется термин CSI (Control Sequince Introducer)
(другие часто встречающиеся в управлении терминалом последовательности -- DCS ESC P (Device Control String), OSC ESC ] (Operating System Command) и ST ESC \ (String Terminator)).
Маленькая демо программа на C/C++
Хотя в документе написано, что если width или height (ширина и высота (количество строк)) опущены, то используется их текущее значение, а если равны нулю, то берутся некоторые значения по умолчанию (display's height or width), но в моих экспериментах с bash-скриптом resize.sh
в обеих случаях окно менялось на стандартный размер 24 х 80 символов.
В Ubuntu 16.04.1 LTS изменение размера окна работает по крайней мере в терминалах gnome-terminal и xfce4-terminal (а вот в xterm версии XTerm(322) ничего не меняется(. )).
Читайте также: