Як перевірити, чи працює моя оболонка в терміналі?


22

Я хочу виконати якусь дію, лише якщо моя оболонка "підключена" до терміналу, тобто лише якщо мій стандартний вхід надходить із входу терміналу, а мій стандартний вихід (а стандартна помилка? Можливо, це не має значення) надрукується / повторюється термінал.

Як я можу це зробити, не покладаючись безпосередньо на специфіку GNU / Linux (наприклад /proc/self)?


Відповіді:


33

isattyє функцією для перевірки цього , і -tпрапор testкоманди робить це доступним із скрипту оболонки:

-t file_descriptor

Вірно, якщо номер дескриптора файлу file_descriptor відкритий і пов'язаний з терміналом. Неправильно, якщо file_descriptor не є дійсним номером дескриптора файлу, або якщо номер дескриптора файлу file_descriptor не відкритий, або якщо він відкритий, але не пов'язаний з терміналом.

Ви можете перевірити, чи FD 0 (стандартний вхід) TTY за допомогою:

test -t 0

Ви можете зробити те ж саме для FD 1 і 2, щоб перевірити вихідні та помилки потоки, або всі вони:

test -t 0 -a -t 1 -a -t 2

Команда повертає 0 (успішно), якщо дескриптори підключені до терміналу, і в іншому випадку помилково.

testтакож доступна як [команда для "тестування дужок":

 if [ -t 0 ] ; then ...

є ідіоматичним способом написання цього умовного.


8

Я думаю, що це дублікат, але я не можу його знайти. Використовуйте

[ -t 0 ]

і

[ -t 1 ]

перевірити відповідно, чи стандартний вхід і вихід підключені до терміналу. man testмає деталі.


7

Лише додаткова примітка поверх тонких відповідей, які вже були надані. Зауважте, що [ -t 0 ]тестує, що дескриптор файлу 0 відкриває один файл, який є файлом пристрою з дисциплінарною строчкою (як правило, це робиться шляхом перевірки того, що нешкідливий термін (и) ioctl () є успішним).

Крім того, це не обов'язково означає, що на іншому кінці є емулятор терміналу або терміналу (з реальним користувачем, який набирає клавіатуру) (хоча в величезній більшості випадків і, мабуть, більшості з них вам важливо, це досить добре наближення).

tty та pty пристрої можуть також використовуватися для передачі даних або як механізм міжпроцесорного зв’язку.

Наприклад, можна зробити:

(stty raw -echo; myscript) < /dev/ttyS0

Для передачі отриманого через RS232 до myscript.

echo test | ssh -tt host myscript

мав би myscriptstdin бути пристроєм pty ( sshdна іншому кінці, і врешті-решт (через ssh-з'єднання) не термінал, а труба, яку подає echo)

Щоб додатково перевірити, чи є термінал на іншому кінці цього рядка RS232 або pty, ви також можете перевірити, чи вказана $TERMзмінна та не порожня ( [ -n "$TERM" ]), і надіслати послідовність виходу звіту про стан пристрою через цей fd і перевірити, чи отримуєте ви відповідь (на додаток до [ -t 0 ]та [ -n "$TERM" ]).

printf >&0 '\e[5n'

Відповідає \e[0nбільшістю терміналів.

Зараз з цим є кілька проблем, тому я б не рекомендував це робити, за винятком випадків, коли ви хочете перевірити це, оскільки ви хочете запустити візуальний додаток TUI (у цьому випадку вам краще використовувати бібліотеки, наприклад ncurses, і замість DSR, ви хочете відправити послідовність ідентифікації пристрою ідентифікації пристрою, щоб запитувати тип терміналу точніше, ніж через $TERM):

  • На щастя, у більшості випадків, коли stdin не є терміналом, він буде відкритий у режимі лише для читання, що призведе printfдо відмови, але у випадку, якщо stdin - це tty-пристрій, відкритий у режимі читання + запису, це матиме побічний ефект надсилання цієї послідовності на інший кінець. Наприклад, у нашому прикладі ssh вище, це фактично відправить послідовність до терміналу (але відповідь не буде надходити на stdin)
  • Відповідь важко читати надійно та переносно. Вам потрібно буде тимчасово змінити дисципліну Tty line і читати по одному байту. Вам також потрібно визначити тайм-аут, до якого, якщо відповідь не буде показана, ви відмовитеся і вирішите, що терміналу немає. Якщо ви хочете розглянути можливість набору людей через супутникові з'єднання, це означає тривалий час.
  • Читання з терміналу, коли у фоновому режимі зупинить ваш сценарій із сигналом SIGTTIN.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.