Что именно означает «устройство ввода не TTY» в выводе «Docker Run»?


18

Это команда, которая работает:

$ echo 'hi there' | docker run -i ubuntu cat
hi there

Эта команда отвечает сообщением об ошибке:

$ echo 'hi there' | docker run -it ubuntu cat
the input device is not a TTY

Я хотел бы выяснить, что именно здесь происходит. Не просто "удалить -t, и это будет исправлено".

Я знаю , что docker run«S -tопция означает„Выделяют псевдо-TTY“, и я читал исторические обзоры о том, что стоит TTY для , но это не помогло мне понять , какой вид договора нарушается здесь.


Это не избыточно, докер может создать TTY, ничего к нему не прикрепляя. Ваш вывод будет содержать символы для цвета и т. Д., Но ваш вывод терминала не будет передан на вход контейнера. Таким образом, введенные вами символы будут поставлены в очередь для следующей команды, которую вы запускаете после выхода из команды docker.
BMitch

Могу ли я запустить tty в докере? У меня есть приложение, которое перестает работать -t, но я не запускаю докер , но не могу изменить команду запуска докера в рабочей среде. Поэтому мне нужно заставить приложение думать, что оно было начато -t.
Мворисек

Ответы:


9

Этот ответ помог мне обернуть голову:

  • по умолчанию (без параметров -iи -tпараметров) контейнер Docker отправляет свой вывод только в STDOUT,
  • с -iопцией приходит подключение к STDIN,
  • -tопция загружает драйвер интерфейса терминала , который работает поверх STDIN / STDOUT. А когда подключается драйвер терминала, связь с контейнером должна соответствовать протоколу интерфейса терминала . Обвязка строки не делает.

7

Поздний ответ, но может помочь кому-то

docker run/exec -iсоединит STDIN команды внутри контейнера с STDIN docker run/execсамого.

Так

  • docker run -i alpine catвыдает пустую строку в ожидании ввода. Типа "привет", вы получаете эхо "привет". Контейнер не выйдет, пока вы не отправите CTRL + D, потому что основной процесс catожидает ввода из бесконечного потока, который является входом терминала для docker run.
  • С другой стороны echo "hello" | docker -i run alpine cat, выведите «hello» и немедленно catвыйдете, потому что замечает, что поток ввода закончился и завершает сам.

Если вы попытаетесь docker psпосле выхода из любого из вышеперечисленных, вы не найдете никаких работающих контейнеров. В обоих случаях catсамо завершение работы завершилось, поэтому docker завершил работу контейнера.

Теперь для "-t" это говорит главному процессу внутри докера, что его вход является терминальным устройством.

Так

  • docker run -t alpine catвыдаст пустую строку, но если вы попытаетесь напечатать "привет", вы не получите никакого эха. Это потому, что хотя catон подключен к входу терминала, этот вход не подключен к вашему входу. «Привет», который вы ввели, не дошел до ввода cat. catждет ввода, который никогда не поступит.
  • echo "hello" | docker run -t alpine cat также даст вам пустую строку и не выйдет из контейнера на CTRL-D, но вы не получите эхо "привет", потому что вы не прошли -i

Если вы отправите CTRL + C, вы вернете свою оболочку, но если вы попробуете docker psсейчас, вы увидите, что catконтейнер все еще работает. Это потому, что catвсе еще ожидает входной поток, который никогда не был закрыт. Я не нашел никакого полезного использования для -tодиночества, не будучи объединенным с -i.

Теперь -itвместе. Это говорит кошке, что ее вход является терминалом и в то же время подключите этот терминал к входу docker runкоторого является терминалом. docker run/execпрежде чем передать его, убедитесь, что его собственный ввод является tty cat. Вот почему вы получите, input device is not a TTYесли попытаетесь, echo "hello" | docker run -it alpine catпотому что в этом случае вход docker runсам по себе является каналом от предыдущего эха, а не терминалом, где docker runвыполняется

Наконец, зачем вам нужно проходить, -tесли вам нужно -iбудет соединить ваш вход catсо входом? Это потому, что команды обрабатывают ввод по-разному, если это терминал. Это также лучше всего иллюстрируется на примере

  • docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -uroot -pдаст вам запрос пароля. Если вы введете пароль, символы будут напечатаны визуально.
  • docker run -i alpine shдаст вам пустую строку. Если вы наберете команду, как lsвы получите вывод, но вы не получите приглашение или цветной вывод.

В последних двух случаях вы получаете это поведение, потому mysqlчто вы shellне обрабатываете ввод как tty и, следовательно, не используете специфическое для tty поведение, такое как маскирование ввода или окрашивание вывода.


4

Tty указывает, что у вас есть терминал, который будет предоставлен xterm или одним из многих интерфейсов командной строки linux. Требуется клавиатура и связанный с ним интерфейс вывода текста. Типичные причины для этого - поддержка вывода цветного текста, обработка различных комбинаций клавиш (например, клавиш со стрелками) и возможность перемещать курсор по экрану.

Когда вы передаете команду в docker, как echoпоказано в вашем примере, этот канал является входным, а этот канал не имеет интерфейса tty, это просто поток текста. Попытка создать tty с этим потерпит неудачу, как указывает сообщение об ошибке.



Для меня все еще есть разрыв между «клавиатурой и выходным интерфейсом» и «STDIN / STDOUT». Очевидно, что вы не можете применить концепцию «положение курсора» к STDOUT, так как STDOUT - это поток, а не экран. Какие спецификации описывают абстракцию выходного интерфейса, которая (я думаю, есть) поверх STDOUT?
Михаил Васин

1
Это интерфейс, который работает поверх stdin / stdout. ru.wikipedia.org/wiki/POSIX_terminal_interface
BMitch
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.