Mendapatkan lebar konsol menggunakan skrip bash

15

Saya menghadapi masalah ketika saya mencoba untuk mendapatkan ukuran terminal dengan menggunakan skrip. Biasanya saya akan menggunakan perintah tput colsdi dalam konsol, namun saya ingin dapat menyelesaikan fitur ini dengan ketat menggunakan skrip.

Sampai sekarang saya dapat mendeteksi konsol yang sedang berjalan dan mendapatkan path file-nya. Namun saya berjuang untuk menggunakan informasi ini untuk mendapatkan lebar konsol. Saya sudah mencoba menggunakan perintah tput, tapi saya cukup baru di Linux / skrip jadi karena itu tidak benar-benar tahu harus berbuat apa.

Alasan untuk melakukan ini adalah saya ingin dapat mengatur entri cron yang memberitahukan konsol lebar / kolomnya sesering mungkin.

Ini kode saya sejauh ini:

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)

Output normal dari TERMINAL& TERMINALPATHare dan , misalnya &pts/terminalnumber/dev/pts/terminalnumberpts/0/dev/pts/0

sirgeezer21
sumber
1
unix.stackexchange.com/questions/16578/… mungkin membantu Anda.
phk
@ php Saya tidak berpikir itu membantu. Masalahnya ada bagaimana cara memberitahu driver tty nilai aktual untuk kolom / baris. Ini dia untuk menentukan mereka dari driver tty.
roaima
Saya tidak berpikir cronpekerjaan memiliki terminal pengendali.
TMN

Jawaban:

17

The tputperintah adalah alat yang sangat baik, tapi sayangnya tidak dapat mengambil pengaturan sebenarnya untuk terminal sewenang-wenang dipilih.

Alasan untuk ini adalah bahwa ia membaca stdout untuk karakteristik terminal, dan ini juga tempat ia menulis jawabannya. Jadi saat Anda mencoba untuk menangkap output tput colsAnda juga telah menghapus sumber informasinya.

Untungnya, sttybacalah stdin daripada stdout untuk penentuan karakteristik terminal, jadi inilah cara Anda dapat mengambil informasi ukuran yang Anda butuhkan:

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

By the way, itu tidak perlu rumit untuk menulis ini sebagai echo $(/usr/bin/tput cols).

Untuk konstruk apa pun yang echo $(some_command)Anda jalankan some_commanddan menangkap outputnya, yang kemudian diteruskan echoke output. Dalam hampir setiap situasi yang dapat Anda bayangkan Anda mungkin juga baru saja menjalankan some_commanddan membiarkannya mengirimkan output secara langsung. Ini lebih efisien dan juga lebih mudah dibaca.

roaima
sumber
Implementasi / versi tput/ yang mana nurses? Milik saya (ncurses 6.0.20160625) melakukan TIOCGWINSZ di stderr jika tidak dapat melakukannya di stdout. cols=$(tput cols)atau cols=$(tput cols 2<> /dev/ttyx) bekerja dengan baik.
Stéphane Chazelas
@ StéphaneChazelas saya punya 5,9 + 20140913-1 + b1 awalnya diinstal dari Debian "sid". Hanya mencari versi yang lebih baru sekarang.
roaima
1
Bekerja dengan baik di ncurses 5.7.20100313sini. Apakah Anda positif cols=$(tput cols 2<> /dev/tty1)tidak bekerja untuk Anda?
Stéphane Chazelas
@ StéphaneChazelas menarik. Anda benar: jika saya memindahkan stdout dari terminal, tput colsapakah membaca dari stderr . Saya sekarang perlu
memikirkan
1
Saya akan menggunakan stty size <"$terminal" | read rows columnsalih-alih mencoba menguraistty -a
Random832
13

tput colsdan tput linesmenanyakan ukuran terminal (dari driver perangkat terminal, bukan terminal itu sendiri) dari perangkat terminal pada stdout-nya, dan jika stdout bukan perangkat terminal seperti dalam kasus di cols=$(tput cols)mana itu kemudian pipa, dari stderr.

Jadi, untuk mengambil nilai dari perangkat terminal yang sewenang-wenang, Anda harus membuka perangkat itu di stderr dari tput:

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

(di sini terbuka dalam mode read-only sehingga tputtidak menampilkan pesan kesalahannya di sana).

Atau, Anda mungkin dapat menggunakan stty size. sttymenanyakan terminal di stdin:

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

Tidak ada yang standar sehingga mungkin (dan dalam praktiknya akan) tidak berfungsi pada semua sistem. Seharusnya ini cukup portabel untuk sistem GNU / Linux.

Penambahan stty sizeatau metode lain untuk meminta ukuran terminal diminta ke POSIX tetapi diskusi tampaknya tidak terjadi di mana saja.

Stéphane Chazelas
sumber
8

Skrip ini:

#!/bin/bash

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

Bekerja di sini dengan tidak ada yang lebih .....

Mengapa Anda mengatur variabel lingkungan dengan data? COLUMNS = $ (/ home / test / Documents / get_columns.sh)

Apakah Anda mencoba mendapatkan kolom dan garis dari skrip atau tty lain? Itu saja? Masih aneh bagi saya karena Anda sedang mengatur variabel lingkungan kolom untuk skrip lokal ....

Luciano Andress Martini
sumber
Ini tidak membantu mengambil nilai-nilai dalam pekerjaan OP cronuntuk terminal tertentu.
roaima
1
Ahn? Apa? Sekarang saya lebih bingung, bagaimana skrip cronjobs dapat memiliki lebar ????? Mereka sebenarnya tidak berjalan di terminal.
Luciano Andress Martini
Aku tahu. The cronpekerjaan query terminal tertentu untuk karakteristiknya. (Saya tidak sepenuhnya yakin mengapa perlu melakukan ini, tapi itulah yang diinginkan OP.)
roaima
@LucianoAndressMartini $ COLUMNS dan $ LINES adalah variabel bash, tidak berfungsi (misalnya) dalam tanda hubung dan posh
ingroxd
Tks. Saya benar-benar tahu, tetapi skrip saya adalah hashbang dengan / bin / bash, saya pikir seharusnya Anda tahu bahwa Anda harus menggunakannya. Jika Anda menggunakan beberapa unix tanpa bash, mungkin jawaban saya bukan untuk Anda.
Luciano Andress Martini
0

Jawaban saya berbeda dari jawaban Roaima, karena ini dinamis. Jawabannya memberi Anda ukuran terminal saat pembuatan. Jika Anda misalnya menggunakan tiling window manager, seperti i3 atau bspwm, Anda lebih suka memiliki lebar terminal saat ini. Jadi saya menggunakan ssty dari paket coreutils:

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

Solusi Luciano bekerja tanpa cela di terminal xterm dan xfce4. Saya tidak tahu apakah semua terminal menetapkan variabel $ COLUMNS.

Sasha
sumber
Ini tidak lebih dinamis dari jawaban saya. Keduanya memberi Anda ukuran terminal pada titik Anda menjalankan perintah.
roaima