Запутался в псевдотерминальном выделении: ssh -t

Вопрос или проблема

Я запутался в том, что делает ssh -t и почему иногда мне нужна опция -t. Насколько я понимаю, если я запускаю ssh -t program, ssh вынужден выделять псевдо tty, с которым он передает ввод с клавиатуры в program и выводит program на stdout.

Но, видимо, я ошибаюсь. Например, следующие два примера, кажется, функционируют одинаково, так как я могу работать интерактивно с rclone, используя любой из них, даже если первая команда заставляет выделять псевдо tty, а вторая команда заставляет не выделять:

  1. ssh -t [email protected] rclone config
  2. ssh -T [email protected] rclone config

Так что же на самом деле делает ssh -t?

Обновление:

Чтобы пролить свет на этот вопрос, я сделал следующий скрипт на Python под названием hello.py.

import sys, signal

def signal_handler(sig, frame):
    print('You pressed Ctrl+C!')
    sys.exit(0)

signal.signal(signal.SIGINT, signal_handler)

print(f"stdin is tty:{sys.stdin.isatty()}")
print(f"stdout is tty:{sys.stdout.isatty()}")

s = input("Enter what you want:")
print("Hello ", s)

На удаленной машине, если я запускаю его как ssh -t [email protected] "python hello.py", я получаю следующий вывод:

stdin is tty: true
stdout is tty: true
Enter what you want: cat
Hello cat

Если я запускаю его как ssh -T [email protected] "python hello.py", я получаю следующее:

stdin is tty: false
stdout is tty: false
Enter what you want: cat
Hello cat

В любом случае, я могу взаимодействовать с программой, вводя “cat” с клавиатуры.

Одно различие, которое я замечаю, заключается в том, что когда я нажимаю CTRL-C, версия с -t захватывает SIGINT, но версия с -T нет.

Интересно, почему я все еще могу взаимодействовать с программой, даже если stdin/stdout не является tty. Также isatty() на самом деле является стандартной библиотечной функцией C. Что действительно означает (псевдо) TTY здесь?

ssh вынужден выделять псевдо tty, с которым он передает ввод с клавиатуры в программу и выводит программу на stdout.

Он делает это, но псевдо tty не является необходимым для работы stdin/stdout. Это также можно достичь с помощью простых пайпов. Когда вы запускаете ssh -T, ввод и вывод удаленной программы подключаются к sshd с использованием анонимных пайпов.

Тем не менее, tty выполняет другие функции – он предоставляет перевод ввода и вывода (например, LF в CRLF или Ctrl-C в сигнал SIGINT), у него есть понятие ‘размеров’ (ширина × высота хранятся как параметры tty). Ядро также ведет специальный учет процессов, прикрепленных к определенному tty, чтобы можно было реализовать управление заданиями (например, Ctrl-Z в оболочке), а также SIGHUP, когда sshd завершает работу, и tty “вешается”, или SIGWINCH, когда размеры изменяются.

(И поскольку интерактивный терминал означает наличие tty, многие программы также проверяют наличие tty на stdin, чтобы определить, нужно ли запускаться в интерактивном режиме или нет. Например, вы можете запустить Bash без tty, но – помимо невозможности выполнения управления заданиями – он также решит отключить свои функции редактирования строк и использовать пустую ‘подсказку’ по умолчанию. Буферизованный ввод/вывод среды выполнения, как Glibc fwrite(), проверит наличие tty, чтобы знать, нужно ли буферизировать построчно для интерактивного вывода или большими порциями для файлового/пайпового вывода.)

Используйте -t, когда вы хотите запустить программу, ориентированную на терминал, такую как htop, и -T, когда вы хотите “чистый” 8-битный канал для передачи бинарных данных. (В общем, единственный раз, когда явный -T необходим, это когда на удаленной стороне есть принудительная команда.)

Ответ или решение

Pseudo-ТTY (псевдотерминал) представляет собой важную концепцию в контексте удаленного подключения через SSH и взаимодействия с программами, требующими интерактивного терминала. Давайте разберем подробно, что такое псевдотерминал, какие функции он выполняет и почему иногда необходимо использовать ключ -t, а иногда -T при выполнении команд SSH.

Теория

Что такое псевдотерминал?

В UNIX-подобных системах терминал – это устройство, которое обрабатывает текстовые данные от пользователя и отправляет их в операционную систему, а также выводит результат работы программы обратно пользователю. Псевдотерминал (PTY) эмулирует функционирование реального терминала, предоставляя программы возможность взаимодействовать в "терминальном" режиме, даже если фактического терминала нет, как, например, в случае удаленного подключения по SSH.

Зачем нужен SSH и опция -t?

SSH или Secure Shell – это протокол, который обеспечивает защищенное удаленное подключение к другим системам в сети. Опция -t в SSH используется для явного задания выделения псевдотерминала. Это необходимо для программ, которые ожидают работы в интерактивной оболочке терминала. Программы, ориентированные на терминал, ожидают получить не только ввод/вывод, но и управляющие сигналы, такие как SIGINT (обычно инициализируемый Ctrl+C), изменение размеров окна (SIGWINCH) и т.п.

Опция -T и ее использование

Обратная опция -T запрещает выделение псевдотерминала. Это может быть полезно в сценариях, где необходимо передавать данные в "чистом" виде без дополнительных преобразований, которые могут быть произвольными в зависимости от терминала, например, при передаче двоичных данных.

Пример

Рассмотрим два примера использования SSH для запуска программ на удаленной машине:

ssh -t [email protected] rclone config

Этот пример показывает, как SSH выделяет псевдотерминал для запуска rclone в интерактивном режиме, поскольку rclone может ожидать интерактивные команды от пользователя.

ssh -T [email protected] rclone config

Здесь отсутствует выделение псевдотерминала, что может быть подходящим для сценариев, где rclone обрабатывает скрипт или команду, не требуя интерактивного режима.

Применение и детали

Использование псевдотерминалов и SSH можно объяснить, выделив несколько ключевых моментов:

  1. Обработка управляющих символов и сигналов: Псевдотерминалы обрабатывают определенные управляющие комбинации клавиш, превращая их в соответствующие сигналы для программ. Например, Ctrl+C может быть переделан в SIGINT, который останавливает процесс.

  2. Эмуляция поведения терминала: Псевдотерминалы могут управлять отображением текста, включая перевод управляющих символов, таких как LF (Line Feed) в CRLF (Carriage Return Line Feed).

  3. Интерактивность и размер окна: Программы могут изменять свое поведение, если они "знают", что работают через терминал (TTY). Размер терминала (ширина и высота) может влиять на то, как отображаются данные (например, в текстовых редакторах или таких утилитах, как htop).

  4. Совместимость с различными оболочками и программами: Некоторое ПО требует наличия интерактивной оболочки для корректной работы. Без псевдотерминала программы могут считывать ввод и вывод через стандартные потоки, но могут отключать функции, которые требуют интерактивных входных данных.

Заключение

Понимание концепции псевдотерминалов и их применения в SSH важно для отрасли ИТ, особенно для специалистов, занимающихся DevOps и системным администрированием. Правильное использование -t и -T может значительно улучшить управляемость скриптов и программ, запущенных на удаленных серверах, избегая неожиданных сбоев и упрощая взаимодействие с терминалами.

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

Оцените материал
Добавить комментарий

Капча загружается...