Отримання ширини консолі за допомогою сценарію bash


15

У мене виникає проблема, коли я намагаюся отримати розмір терміналу за допомогою скриптів. Як правило, я використовував би команду tput colsвсередині консолі, однак хочу виконати цю функцію шляхом суворого використання скриптів.

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

Причиною цього є те, що я хочу мати можливість встановити запис крона, який так часто повідомляє консоль про свою ширину / стовпці.

Це мій код поки що:

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_column.sh

#!/usr/bin/env bash
echo $(/usr/bin/tput cols)

Нормальний вихід TERMINALі TERMINALPATHє , і , наприклад , &pts/terminalnumber/dev/pts/terminalnumberpts/0/dev/pts/0


1
unix.stackexchange.com/questions/16578/… може допомогти вам.
phk

@phk Я не думаю, що це допомагає. Проблема полягає в тому, як повідомити драйверу tty фактичні значення для стовпців / рядків. Ось їх слід визначити з драйвера tty.
roaima

Я не думав, що в cronробочих місцях є контрольні термінали.
TMN

Відповіді:


18

tputКоманда є відмінним інструментом, але , до жаль , він не може отримати фактичні параметри довільно обраний термінал.

Причиною цього є те, що він читає stdout для термінальних характеристик, і саме там він пише свою відповідь. Тому в момент, коли ви намагаєтеся зафіксувати результат, 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і дозволити їй доставити свої результати безпосередньо. Це більш ефективно, а також легше читати.


Яка реалізація / версія 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, спочатку встановлений із Deid "sid". Просто шукаю нову версію зараз.
roaima

1
Тут добре працює ncurses 5.7.20100313. Ви впевнені, cols=$(tput cols 2<> /dev/tty1)що для вас не працює?
Стефан Шазелас

@ StéphaneChazelas зачаровує. Ви маєте рацію: якщо я відсуну stdout від терміналу, tput colsчитатиме з stderr . Мені зараз потрібно розібратися, як переписати свою відповідь ...
roaima

1
Я б використав stty size <"$terminal" | read rows columnsзамість спроби розборуstty -a
Random832

13

tput colsі tput linesзапитувати розмір терміналу (від драйвера термінального пристрою, а не самого терміналу) від термінального пристрою на його stdout, і якщо stdout не є термінальним пристроєм, як у випадку, cols=$(tput cols)коли це тоді труба, від stderr.

Отже, щоб отримати значення з довільного термінального пристрою, потрібно відкрити цей пристрій на stderr tput:

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

(тут відкрито в режимі лише для читання, тому tputне надсилає туди своїх повідомлень про помилки).

Або ви можете використовувати stty size. sttyзапитує термінал на stdin:

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

Жоден із них не є стандартним, тому може (і на практиці) не працюватиме у всіх системах. Він повинен бути досить портативним для систем GNU / Linux.

Додавання stty sizeабо іншого методу до запиту розміру терміналу було запрошено до POSIX, але, здається, обговорення нікуди не йде.


9

Цей сценарій:

#!/bin/bash

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

Працювали тут абсолютно нічого більше .....

Чому ви встановлюєте змінну середовища з даними? COLUMNS = $ (/ домашня / тест / Документи / get_column.sh)

Ви намагаєтеся отримати стовпці та рядки з іншого сценарію чи tty? Є те, що його? Для мене все ще дивно, оскільки ви встановлюєте змінну середовища стовпців для локального сценарію ....


Це не допомагає отримати значення в заданні ОП cronдля певного терміналу.
roaima

1
Ан? Що? Тепер я більше розгублений, як скрипти cronjobs можуть мати ширину ????? Вони фактично не працюють в терміналі.
Лучано Андресс Мартіні

Я знаю. Завдання cronзапитує певний термінал щодо його характеристик. (Я не зовсім впевнений, для чого це потрібно робити, але саме цього хоче ОП.)
roaima

@LucianoAndressMartini $ COLUMNS та $ LINES є змінними bash, вона не працює (наприклад) у тире та posh
ingroxd

Ткс. Я справді знаю, але мій сценарій є хешбангом з / bin / bash, я думаю, ви повинні знати, що ви повинні ним користуватися. Якщо ви використовуєте якийсь unix без bash, можливо, моя відповідь не для вас.
Luciano Andress Martini

1

Моя відповідь відрізняється від відповіді Роайма, оскільки вона динамічна. Його / її відповідь дає вам розмір терміналу під час створення. Якщо ви, наприклад, використовуєте менеджер віконних плиток, наприклад, i3 або bspwm, ви хочете мати поточну ширину терміналу. Таким чином, я використовую ssty з пакету coreutils:

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

Рішення Luciano працює бездоганно в xterm та xfce4-терміналі. Я не знаю, чи всі термінали встановлюють змінну $ COLUMNS.


Це не більш динамічно, ніж моя відповідь. Обидва надають вам термінальний розмір у точці, де ви запускаєте команди.
roaima
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.