Co dokładnie „urządzenie wejściowe nie jest TTY” dokładnie na wyjściu „pracy dokera”?

18

To polecenie działa:

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

To polecenie odpowiada komunikatem o błędzie:

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

Chciałbym dowiedzieć się dokładnie, co się tutaj dzieje. Nie tylko „usuń -t i zostanie to naprawione”.

Wiem, że docker run„s -topcja oznacza«Przydzielanie pseudo-TTY», i czytałem historycznych przeglądy co stoi na TTY , ale to nie pomogło mi zrozumieć, jaki rodzaj umowy jest naruszone tutaj.

Michaił Vasin
źródło
To nie jest zbędne, doker może utworzyć TTY bez dołączania do niego czegokolwiek. Dane wyjściowe miałyby znaki koloru, itp., Ale dane wyjściowe terminala nie byłyby przesyłane do wejścia kontenera. Tak więc znaki, które wpisujesz byłyby w kolejce dla następnego polecenia uruchamianego po wyjściu polecenia dokowania.
BMitch
Czy mogę uruchomić tty w oknie dokowanym? Mam aplikację, która przestaje działać, ale nie uruchamiam dokera -t, ale nie mogę zmodyfikować polecenia startu dokera w produkcji. Muszę więc sprawić, by aplikacja zaczęła myśleć -t.
mvorisek,

Odpowiedzi:

9

Ta odpowiedź pomogła mi owinąć głowę:

  • domyślnie (bez -iani -topcji) kontener Docker wysyła dane wyjściowe do STDOUT,
  • z -iopcją jest połączenie ze STDIN,
  • -topcja pobiera sterownik interfejsu terminala , który działa na STDIN / STDOUT. A kiedy wciągnięty jest sterownik terminalu, komunikacja z kontenerem musi być zgodna z protokołem interfejsu terminalu . Rurociągi łańcucha nie.
Michaił Vasin
źródło
7

Późna odpowiedź, ale może komuś pomóc

docker run/exec -ipołączy STDIN polecenia wewnątrz kontenera z STDIN docker run/execsamego.

Więc

  • docker run -i alpine catdaje pustą linię czekającą na dane wejściowe. Wpisz „cześć”, otrzymasz echo „cześć”. Kontener nie zostanie zamknięty, dopóki nie wyślesz CTRL + D, ponieważ główny proces catczeka na dane wejściowe ze strumienia nieskończonego, który jest wejściem końcowym pliku docker run.
  • Z drugiej strony echo "hello" | docker -i run alpine catwypisuje „cześć” i kończy natychmiast, ponieważ catzauważa, że ​​strumień wejściowy zakończył się i sam się kończy.

Jeśli spróbujesz docker pspo wyjściu z jednego z powyższych, nie znajdziesz żadnych uruchomionych kontenerów. W obu przypadkach catsamo się zakończyło, więc doker zakończył kontener.

Teraz dla „-t” mówi to głównemu procesowi wewnątrz dokera, że ​​jego wejście jest urządzeniem końcowym.

Więc

  • docker run -t alpine catda ci pustą linię, ale jeśli spróbujesz wpisać „cześć”, nie usłyszysz żadnego echa. Wynika to z faktu, że chociaż catjest on podłączony do wejścia terminala, to wejście nie jest podłączone do twojego wejścia. Wpisane słowo „cześć” nie dotarło do wejścia cat. catczeka na dane wejściowe, które nigdy nie docierają.
  • echo "hello" | docker run -t alpine cat da ci również pustą linię i nie opuści kontenera na CTRL-D, ale nie dostaniesz echa „cześć”, ponieważ nie przeszedłeś -i

Jeśli wyślesz CTRL + C, odzyskasz swoją powłokę, ale jeśli spróbujesz docker psteraz, zobaczysz, że catkontener nadal działa. Jest tak, ponieważ catwciąż czeka na strumień wejściowy, który nigdy nie został zamknięty. Nie znalazłem żadnego przydatnego zastosowania dla -tsamego bez połączenia -i.

Teraz -itrazem. Mówi to kotowi, że jego wejściem jest terminal i jednocześnie podłącz ten terminal do wejścia, docker runktórego terminalem jest. docker run/execupewni się, że jego dane wejściowe są w rzeczywistości tty przed przekazaniem go cat. Dlatego dostaniesz a, input device is not a TTYjeśli spróbujesz, echo "hello" | docker run -it alpine catponieważ w tym przypadku wejściem docker runjest potok z poprzedniego echa, a nie terminal, w którym docker runjest wykonywany

Na koniec, dlaczego musiałbyś zdać, -tjeśli -ipodołasz, aby połączyć swój wkład z catwejściem? Jest tak, ponieważ polecenia traktują dane wejściowe inaczej, jeśli jest to terminal. Najlepiej ilustruje to również przykład

  • docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -uroot -pwyświetli monit o hasło. Jeśli wpiszesz hasło, znaki zostaną wydrukowane w widoczny sposób.
  • docker run -i alpine shda ci pustą linię. Jeśli wpiszesz polecenie, tak jak lsotrzymasz wynik, ale nie pojawi się monit lub kolorowe wyjście.

W dwóch ostatnich przypadkach, masz ten problem, bo mysqljak shellnie traktowali jako wejście tty, a zatem nie używać tty specyficzne zachowanie jak maskowanie wejścia lub kolorowania wyjście.

Ahmed Ghonim
źródło
4

Tty oznacza, że ​​masz terminal, coś, co może zapewnić xterm lub jeden z wielu interfejsów linii poleceń Linux. Potrzebuje powiązanego z nim interfejsu klawiatury i wyjścia tekstowego. Typowe powody, dla których warto to robić, to obsługa kolorowego tekstu wyjściowego, obsługa różnych kombinacji klawiszy (takich jak klawisze strzałek) i możliwość przesuwania kursora po ekranie.

Kiedy potokujesz polecenie do okna dokowanego, tak jak w echoprzykładzie, ten potok jest wejściem, a potok nie ma interfejsu tty, to tylko strumień tekstu. Próba utworzenia tty z tym zakończy się niepowodzeniem, jak wskazuje komunikat o błędzie.

BMitch
źródło
Zobacz także: stackoverflow.com/a/43099210/596285
BMitch
Wciąż jest dla mnie luka między „klawiaturą a interfejsem wyjściowym” i „STDIN / STDOUT”. Oczywiście nie można zastosować koncepcji „pozycji kursora” do STDOUT, ponieważ STDOUT jest strumieniem, a nie ekranem. Jakie specyfikacje opisują abstrakcję interfejsu wyjściowego, która (jak sądzę jest) na STDOUT?
Michaił Vasin
1
Jest to interfejs działający na stdin / stdout. en.wikipedia.org/wiki/POSIX_terminal_interface
BMitch