Получение ширины консоли с помощью bash-скрипта

15

Я столкнулся с проблемой, когда я пытаюсь получить размер терминала с помощью сценариев. Обычно я использую команду tput colsвнутри консоли, однако я хочу иметь возможность выполнить эту функцию, строго используя сценарии.

На данный момент я могу определить работающую консоль и получить путь к файлу. Однако я изо всех сил пытаюсь использовать эту информацию, чтобы получить ширину консоли. Я пытался использовать команду tput, но я довольно плохо знаком с Linux / скриптами, поэтому не знаю, что делать.

Причина для этого в том, что я хочу иметь возможность настроить запись cron, которая время от времени уведомляет консоль о ее ширине / столбцах.

Это мой код до сих пор:

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)

Нормальный вывод TERMINAL& TERMINALPATHесть и , например &pts/terminalnumber/dev/pts/terminalnumberpts/0/dev/pts/0

sirgeezer21
источник
1
unix.stackexchange.com/questions/16578/… может помочь вам.
PhK
@ phk Не думаю, что это помогает. Вопрос в том, как сообщить драйверу tty фактических значений для столбцов / строк. Вот это, чтобы определить их из tty драйвера.
Ройма
Я не думал, что у cronрабочих мест были контрольные терминалы.
TMN

Ответы:

18

Команда tputявляется отличным инструментом, но, к сожалению, она не может получить фактические настройки для произвольно выбранного терминала.

Причина этого в том, что он читает стандартный вывод для характеристик терминала, и это также то, где он пишет свой ответ. Таким образом, в момент, когда вы пытаетесь захватить вывод, tput colsвы также удалили источник его информации.

К счастью, sttyчитает stdin, а не stdout для определения характеристик терминала, поэтому вы можете получить необходимую информацию о размере:

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

Кстати, излишне громоздко писать это как echo $(/usr/bin/tput cols).

Для любой конструкции echo $(some_command)вы выполняете some_commandи захватываете ее выходные данные, которые затем передаете echoв выходные данные. Вы можете себе представить, что почти в любой ситуации вы просто запускаете some_commandи позволяете ему напрямую выводить результаты. Это более эффективно, а также легче читать.

roaima
источник
Какая реализация / версия tput/ nurses? Мой (ncurses 6.0.20160625) делает TIOCGWINSZ на stderr, если он не может сделать это на stdout. cols=$(tput cols)или cols=$(tput cols 2<> /dev/ttyx) работает просто отлично.
Стефан Шазелас
@ StéphaneChazelas У меня 5.9 + 20140913-1 + b1, изначально установленный из Debian "sid". Просто ищу новую версию сейчас.
Ройма
1
Работает также и ncurses 5.7.20100313здесь. Вы уверены, cols=$(tput cols 2<> /dev/tty1)что не работает для вас?
Стефан Шазелас
@ StéphaneChazelas увлекательно. Вы правы: если я перееду стандартный вывод от терминала, tput colsэто читать STDERR . Теперь мне нужно решить, как переписать мой ответ ...
Ройма
1
Я бы использовал stty size <"$terminal" | read rows columnsвместо того, чтобы пытаться разобратьstty -a
Random832
13

tput colsи tput linesзапросить размер терминала (из драйвера терминального устройства, а не самого терминала) у терминального устройства на его stdout, и, если stdout не является терминальным устройством, как в случае, cols=$(tput cols)где это тогда канал, из stderr.

Таким образом, чтобы извлечь значения из произвольного оконечного устройства, вам нужно открыть это устройство в строке tput:

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

(здесь открывается в режиме только для чтения, поэтому tputтам не выводятся сообщения об ошибках).

Кроме того, вы можете использовать stty size. sttyзапрашивает терминал на stdin:

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

Ни один из них не является стандартным, поэтому может (и на практике не будет) работать на всех системах. Он должен быть достаточно переносимым для систем GNU / Linux.

В stty sizePOSIX было запрошено добавление или другой метод для запроса размера терминала, но обсуждение, похоже, никуда не денется.

Стефан Шазелас
источник
8

Этот скрипт:

#!/bin/bash

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

Работал здесь абсолютно ничего больше .....

Почему вы устанавливаете переменную среды с данными? COLUMNS = $ (/ дома / испытания / Документы / get_columns.sh)

Вы пытаетесь получить столбцы и строки из другого скрипта или tty? Это оно? Все еще странно для меня, потому что вы устанавливаете переменную окружения столбцов для локального сценария ....

Лучано Андресс Мартини
источник
Это не помогает получить значения в работе OP cronдля конкретного терминала.
Ройма
1
Ahn? Какая? Теперь я более запутался, как скрипты cronjobs могут иметь ширину ????? Они на самом деле не работают в терминале.
Лучано Андресс Мартини
Я знаю. cronРабота запрашивает конкретный терминал для его характеристик. (Я не совсем уверен, почему он должен это делать, но это то, чего хочет ОП.)
Ройма
@LucianoAndressMartini $ COLUMNS и $ LINES являются переменными bash, они не работают (например, в dash и posh
ingroxd
Tks. Я действительно знаю, но мой сценарий - hashbang с / bin / bash, я думаю, что вы должны знать, что вы должны его использовать. Если вы используете Unix без Bash, возможно, мой ответ не для вас.
Лучано Андресс Мартини,
1

Мой ответ отличается от ответа Роймы, так как он динамичен. Его / Hers ответ дает вам размер терминала при создании. Если вы, например, используете менеджер окон, например i3 или bspwm, вы бы предпочли иметь текущую ширину терминала. Поэтому я использую ssty из пакета coreutils:

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

Решение Лучано работает безупречно в xterm и xfce4-терминал. Я не знаю, все ли терминалы устанавливают переменную $ COLUMNS.

Саша
источник
Это не более динамично, чем мой ответ. Оба дают вам размер терминала в тот момент, когда вы запускаете команды.
Роайма