Uzyskiwanie szerokości konsoli za pomocą skryptu bash

15

Występuje problem polegający na tym, że próbuję uzyskać rozmiar terminala za pomocą skryptów. Normalnie używałbym polecenia tput colswewnątrz konsoli, jednak chcę móc tę funkcję osiągnąć poprzez ścisłe używanie skryptów.

Obecnie jestem w stanie wykryć działającą konsolę i uzyskać ścieżkę do pliku. Jednak staram się wykorzystać te informacje, aby uzyskać szerokość konsoli. Próbowałem użyć tego polecenia tput, ale jestem całkiem nowy w Linuksie / skryptach, więc tak naprawdę nie wiem, co robić.

Powodem tego jest to, że chcę mieć możliwość ustawienia wpisu cron, który co jakiś czas informuje konsolę o jego szerokości / kolumnach.

Oto mój kod do tej pory:

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)

Normalna wydajność TERMINAL& TERMINALPATHto i , na przykład &pts/terminalnumber/dev/pts/terminalnumberpts/0/dev/pts/0

sirgeezer21
źródło
@phk Nie sądzę, że to pomaga. Problem polega na tym, jak powiedzieć sterownikowi tty rzeczywistych wartości dla kolumn / linii. Tutaj należy je ustalić na podstawie sterownika tty.
roaima
Nie sądziłem, że cronpraca ma kontrolowane terminale.
TMN

Odpowiedzi:

18

tputKomenda jest doskonałym narzędziem, ale niestety nie może pobierać aktualne ustawienia dla dowolnie wybranego terminalu.

Powodem tego jest to, że odczytuje stdout dla cech terminalu, i tutaj również zapisuje swoją odpowiedź. Tak więc w chwili, gdy próbujesz uchwycić tput colstwój wynik, usunąłeś również źródło jego informacji.

Na szczęście sttyczyta standardowe celu ustalenia charakterystyki terminalu zamiast stdout , więc w ten sposób możesz uzyskać potrzebne informacje o rozmiarze:

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

Nawiasem mówiąc, niepotrzebnie kłopotliwe jest pisanie tego jako echo $(/usr/bin/tput cols).

Dla każdego echo $(some_command)uruchomionego konstruktu some_commandi przechwytywania jego wyniku, który następnie przekazujesz echodo wyjścia. W prawie każdej sytuacji można sobie wyobrazić, że równie dobrze mógłbyś po prostu uruchomić some_commandi pozwolić, aby dostarczał swoją moc bezpośrednio. Jest bardziej wydajny i łatwiejszy do odczytania.

roaima
źródło
Która implementacja / wersja tput/ nurses? Mój (ncurses 6.0.20160625) robi TIOCGWINSZ na stderr, jeśli nie może tego zrobić na stdout. cols=$(tput cols)lub cols=$(tput cols 2<> /dev/ttyx) działa dobrze.
Stéphane Chazelas
@ StéphaneChazelas Mam 5.9 + 20140913-1 + b1 oryginalnie zainstalowany z Debiana „sid”. Po prostu szukam teraz nowszej wersji.
roaima
1
Działa również ncurses 5.7.20100313tutaj. Czy jesteś pewien, cols=$(tput cols 2<> /dev/tty1)że nie działa dla ciebie?
Stéphane Chazelas
@ StéphaneChazelas fascynujące. Masz rację: jeśli odsunę stdout od terminala, tput colsczyta stderr . Muszę teraz wymyślić, jak przepisać moją odpowiedź ...
roaima,
1
Chciałbym użyć stty size <"$terminal" | read rows columnszamiast próbować analizowaćstty -a
Random832
13

tput colsi tput lineszapytaj o rozmiar terminala (ze sterownika urządzenia końcowego, a nie samego terminala) z urządzenia końcowego na jego standardowym wyjściu, a jeśli standardowe wyjście nie jest urządzeniem końcowym, tak jak w przypadku, cols=$(tput cols)gdy jest to rura, ze stderr.

Tak więc, aby pobrać wartości z dowolnego urządzenia końcowego, musisz otworzyć to urządzenie na stderr tput:

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

(tutaj otwarte w trybie tylko do odczytu, więc tput nie wyświetla tam swoich komunikatów o błędach).

Alternatywnie możesz być w stanie użyć stty size. sttyodpytuje terminal na standardowym wejściu:

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

Żadne z nich nie są standardowe, więc może (i w praktyce) nie działać na wszystkich systemach. Powinien być jednak dość przenośny na systemy GNU / Linux.

Do stty sizePOSIX zażądano dodania lub innej metody zapytania o rozmiar terminala, ale wydaje się, że dyskusja nigdzie się nie kończy.

Stéphane Chazelas
źródło
9

Ten skrypt:

#!/bin/bash

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

Pracowałem tutaj z absolutnie niczym więcej .....

Dlaczego ustawiasz zmienną środowiskową za pomocą danych? COLUMNS = $ (/ home / test / Documents / get_columns.sh)

Czy próbujesz uzyskać kolumny i wiersze z innego skryptu lub tty? Czy to to? Wciąż dziwne dla mnie, ponieważ ustawiasz zmienną środowiskową kolumn dla lokalnego skryptu ...

Luciano Andress Martini
źródło
To nie pomaga odzyskać wartości w ramach cronzadania OP dla konkretnego terminala.
roaima
1
Ahn? Co? Teraz jestem bardziej zdezorientowany, w jaki sposób skrypty cronjobs mogą mieć szerokość ????? W rzeczywistości nie działają w terminalu.
Luciano Andress Martini
Wiem. Zadanie cronsprawdza konkretny terminal pod kątem jego właściwości. (Nie jestem do końca pewien, dlaczego musi to robić, ale tego właśnie chce OP).
roaima
@LucianoAndressMartini $ COLUMNS i $ LINES są zmiennymi bash, nie działa (na przykład) w myślniku i posh
ingroxd
Tks. Naprawdę wiem, ale mój skrypt to hashbang z / bin / bash. Myślę, że powinieneś wiedzieć, że powinieneś go używać. Jeśli używasz Uniksa bez basha, być może moja odpowiedź nie jest dla ciebie.
Luciano Andress Martini,
1

Moja odpowiedź różni się od odpowiedzi Roaimy, ponieważ jest dynamiczna. Jego / Jej odpowiedź daje rozmiar terminalu podczas tworzenia. Jeśli na przykład używasz menedżera okien sąsiadujących, takiego jak i3 lub bspwm, wolisz mieć bieżącą szerokość terminala. Dlatego używam ssty z pakietu coreutils:

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

Rozwiązanie Luciano działa bez zarzutu w terminalach xterm i xfce4. Nie wiem, czy wszystkie terminale ustawiają zmienną $ COLUMNS.

Sasha
źródło
To nie jest bardziej dynamiczne niż moja odpowiedź. Oba dają ci rozmiar terminala w miejscu, w którym uruchamiasz polecenia.
roaima