Thiết bị đầu vào có nghĩa gì không phải là một TTYvà có nghĩa là gì trong đầu ra của docker chạy ra?


18

Đây là một lệnh hoạt động:

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

Đây là lệnh phản hồi với thông báo lỗi:

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

Tôi muốn tìm hiểu chính xác những gì xảy ra ở đây. Không chỉ "xóa -t và nó sẽ được sửa".

Tôi biết rằng docker run's -tlựa chọn là viết tắt của 'Phân bổ một pseudo-TTY', và tôi đã đọc tổng quan lịch sử những gì TTY là viết tắt của , nhưng nó không giúp tôi hiểu những gì loại hợp đồng bị vi phạm ở đây.


Nó không dư thừa, docker có thể tạo TTY mà không cần gắn bất cứ thứ gì vào nó. Đầu ra của bạn sẽ có các ký tự cho màu, v.v., nhưng đầu ra đầu cuối của bạn sẽ không được dẫn vào đầu vào của container. Vì vậy, các ký tự bạn nhập sẽ được xếp hàng cho lệnh tiếp theo bạn chạy sau khi lệnh docker thoát.
BMitch

Tôi có thể bắt đầu tty trong docker không? Tôi có một số ứng dụng ngừng hoạt động Tôi không chạy docker với -t, nhưng tôi không thể sửa đổi lệnh bắt đầu docker trong sản xuất. Vì vậy, tôi cần phải làm cho ứng dụng nghĩ rằng nó đã được bắt đầu với -t.
mvorisek

Câu trả lời:


9

Câu trả lời này đã giúp tôi quấn đầu:

  • theo mặc định (không có không phải -ivà cũng không -ttùy chọn) một container Docker chỉ gửi sản lượng của nó để STDOUT,
  • với -itùy chọn đi kèm với STDIN,
  • -ttùy chọn kéo vào trình điều khiển giao diện đầu cuối , hoạt động trên STDIN / STDOUT. Và khi trình điều khiển đầu cuối được kéo vào, giao tiếp với một thùng chứa phải tuân theo giao thức giao diện đầu cuối . Đường ống một chuỗi không.

7

Trả lời muộn, nhưng có thể giúp được ai đó

docker run/exec -isẽ kết nối STDIN của lệnh bên trong container với STDIN của docker run/execchính nó.

Vì thế

  • docker run -i alpine catcung cấp cho bạn một dòng trống chờ đầu vào. Nhập "xin chào" bạn sẽ nhận được tiếng vang "xin chào". Container sẽ không thoát cho đến khi bạn gửi CTRL + D vì quá trình chính catđang chờ đầu vào từ luồng vô hạn là đầu vào cuối của docker run.
  • Mặt khác echo "hello" | docker -i run alpine catsẽ in "xin chào" và thoát ngay lập tức vì catthông báo rằng luồng đầu vào đã kết thúc và tự chấm dứt.

Nếu bạn thử docker pssau khi thoát khỏi một trong những điều trên, bạn sẽ không tìm thấy bất kỳ container nào đang chạy. Trong cả hai trường hợp, catchính nó đã chấm dứt, do đó docker đã chấm dứt container.

Bây giờ cho "-t", điều này cho biết quy trình chính bên trong docker rằng đầu vào của nó là một thiết bị đầu cuối.

Vì thế

  • docker run -t alpine catsẽ cung cấp cho bạn một dòng trống, nhưng nếu bạn cố gắng gõ "xin chào", bạn sẽ không nhận được bất kỳ tiếng vang nào. Điều này là do trong khi catđược kết nối với đầu vào đầu cuối, đầu vào này không được kết nối với đầu vào của bạn. "Xin chào" mà bạn đã nhập không đạt đến đầu vào cat. catđang chờ đầu vào không bao giờ đến
  • echo "hello" | docker run -t alpine cat cũng sẽ cung cấp cho bạn một dòng trống và sẽ không thoát khỏi vùng chứa trên CTRL-D nhưng bạn sẽ không nhận được tiếng vang "xin chào" vì bạn đã không vượt qua -i

Nếu bạn gửi CTRL + C, bạn sẽ lấy lại được vỏ của mình, nhưng nếu bạn thử docker psngay bây giờ, bạn sẽ thấy catcontainer vẫn đang chạy. Điều này là do catvẫn đang chờ đợi một luồng đầu vào không bao giờ bị đóng. Tôi đã không tìm thấy bất kỳ sử dụng hữu ích cho -tmột mình mà không được kết hợp với -i.

Bây giờ, cho -itcùng nhau. Điều này cho mèo biết rằng đầu vào của nó là một thiết bị đầu cuối và đồng thời kết nối thiết bị đầu cuối này với đầu vào docker runlà thiết bị đầu cuối. docker run/execsẽ đảm bảo rằng đầu vào của chính nó trong thực tế là một tty trước khi chuyển nó đến cat. Đây là lý do tại sao bạn sẽ nhận được input device is not a TTYnếu bạn cố gắng echo "hello" | docker run -it alpine catvì trong trường hợp này, đầu vào của docker runchính nó là đường ống từ tiếng vang trước đó và không phải là thiết bị đầu cuối nơi docker runđược thực thi

Cuối cùng, tại sao bạn cần phải vượt qua -tnếu -isẽ thực hiện thủ thuật kết nối đầu vào của bạn với catđầu vào của? Điều này là do các lệnh xử lý đầu vào khác nhau nếu đó là một thiết bị đầu cuối. Điều này cũng được minh họa tốt nhất bằng ví dụ

  • docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -uroot -psẽ cung cấp cho bạn một dấu nhắc mật khẩu. Nếu bạn nhập mật khẩu, các ký tự được in rõ ràng.
  • docker run -i alpine shsẽ cung cấp cho bạn một dòng trống. Nếu bạn gõ một lệnh như lsbạn nhận được một đầu ra, nhưng bạn sẽ không nhận được một dấu nhắc hoặc đầu ra màu.

Trong hai trường hợp cuối cùng, bạn có hành vi này vì mysqlcũng như shellkhông coi đầu vào là tty và do đó không sử dụng hành vi cụ thể tty như che dấu đầu vào hoặc tô màu đầu ra.


4

Một tty chỉ ra rằng bạn có một thiết bị đầu cuối, một cái gì đó sẽ được cung cấp bởi xterm hoặc một trong nhiều giao diện dòng lệnh linux. Nó cần một bàn phím và giao diện đầu ra văn bản liên quan đến nó. Những lý do điển hình muốn điều này là để hỗ trợ đầu ra văn bản màu, xử lý các tổ hợp phím khác nhau (như các phím mũi tên) và khả năng di chuyển con trỏ quanh màn hình.

Khi bạn chuyển một lệnh vào docker như echoví dụ của bạn cho thấy, đường ống đó là đầu vào và đường ống đó không có giao diện tty, đó chỉ là một dòng văn bản. Cố gắng tạo một tty với điều đó sẽ thất bại như thông báo lỗi cho biết.



Vẫn còn một khoảng cách đối với tôi giữa "bàn phím và giao diện đầu ra" và "STDIN / STDOUT". Rõ ràng bạn không thể áp dụng khái niệm "vị trí con trỏ" cho STDOUT, vì STDOUT là một luồng chứ không phải màn hình. Những thông số kỹ thuật nào mô tả sự trừu tượng hóa giao diện đầu ra (tôi đoán là) trên đầu trang của STDOUT?
Mikhail Vasin

1
Đó là một giao diện chạy trên stdin / stdout. vi.wikipedia.org/wiki/POSIX_terminal_interface
BMitch
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.