Що точно означає "пристрій введення не TTY"?


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.
mvorisek

Відповіді:


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буде надруковано "привіт" і негайно вийти, оскільки catпомітить, що вхідний потік закінчився і припиняється сам.

Якщо ви спробуєте docker psпісля виходу з будь-якого з перерахованих вище, ви не знайдете жодних запущених контейнерів. В обох випадках catсам припинився, таким чином докер припинив контейнер.

Тепер для "-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переконайтесь, що його власний вклад є насправді десятки перед тим, як передавати його 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. Потрібна клавіатура та інтерфейс виводу тексту, пов'язаний з ним. Типова причина цього - підтримка виводу кольорового тексту, обробка різних комбінацій клавіш (наприклад, клавіш зі стрілками) та можливість переміщення курсору по екрану.

Коли ви echoпередаєте команду в docker, як показує ваш приклад, ця труба є входом, і ця труба не має tty інтерфейсу, це лише потік тексту. Спроба створити tty з цим не вдасться, як вказує повідомлення про помилку.


Дивіться також: stackoverflow.com/a/43099210/596285
BMitch

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

1
Це інтерфейс, який працює поверх stdin / stdout. en.wikipedia.org/wiki/POSIX_terminal_interface
BMitch
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.