Làm thế nào (và tại sao) sử dụng stderr cho cả đọc và viết?


12

Theo câu trả lời này của schily , lessđọc các lệnh điều hướng từ stderr nếu nó không thể mở /dev/tty.

Điều này có vẻ khó hiểu, vì tôi chưa bao giờ thấy bất cứ điều gì viết vào luồng stderr của chương trình khác, và tôi không biết làm thế nào tôi thậm chí sẽ hoàn thành điều đó.

Mục đích của stderr là mở cho cả đọc và viết là gì? Và nếu điều này hữu ích, làm thế nào để tôi sử dụng nó trên các hệ thống hiện đại? (Có một số cú pháp phức tạp để chuyển một cái gì đó vào stderr thay vì stdin chẳng hạn?)

Câu trả lời:


7

Tôi đã rất ngạc nhiên lúc đầu. Tuy nhiên sau khi đọc câu trả lời, và làm một cuộc điều tra nhỏ, nó có vẻ đơn giản. Vì vậy, đây là những gì tôi đã tìm thấy. (cuối cùng không có gì bất ngờ.)

Trước khi chuyển hướng stdin, stdout và stderr như mong đợi được kết nối với cùng một thiết bị.

#ctrl-alt-delor:~$
#↳ ll /dev/std*
lrwxrwxrwx 1 root root 15 Jun  3 20:58 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 Jun  3 20:58 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 Jun  3 20:58 /dev/stdout -> /proc/self/fd/1

#ctrl-alt-delor:~$
#↳ ll /proc/self/fd/*
lrwx------ 1 richard richard 64 Jun 30 19:14 /proc/self/fd/0 -> /dev/pts/12
lrwx------ 1 richard richard 64 Jun 30 19:14 /proc/self/fd/1 -> /dev/pts/12
lrwx------ 1 richard richard 64 Jun 30 19:14 /proc/self/fd/2 -> /dev/pts/12

Do đó, sau hầu hết các hướng dẫn lại (đó là nếu stderr) không được chuyển hướng. stderr vẫn được kết nối với thiết bị đầu cuối. Do đó, nó có thể được đọc, để có được đầu vào bàn phím.

Điều duy nhất ngăn chặn các tệp đang được sử dụng theo hướng bất ngờ là quy ước và các đường ống là đơn hướng.

Một ví dụ khác, hãy thử:

cat | less

Điều này sai sau một trang, khi lesscố gắng đọc thiết bị đầu cuối (điều này không gây ngạc nhiên, cũng như catđọc thiết bị đầu cuối).

/dev/ttylà bí ẩn hơn, nó không phải là một liên kết vào /proc/self.

#ctrl-alt-delor:~$
#↳ ll /dev/tty
crw-rw-rw- 1 root tty 5, 0 Jun 29 09:18 /dev/tty

Xem những mối quan hệ giữa thiết bị đầu cuối kiểm soát hiện tại của tôi và `/ dev / tty`? cho một cuộc thám hiểm. Cảm ơn @StephenKitt cho liên kết.


Về /dev/tty, xem câu hỏi này .
Stephen Kitt

6

Khi bạn đăng nhập, stdin, stdout và stderr được kết nối với thiết bị đầu cuối từ nơi bạn đăng nhập. Nói chính xác hơn, tty được mở theo kiểu chữ và stdout và stderr là kết quả từ hai dup(2)thao tác trên bộ mô tả tệp đầu tiên. Điều này cho phép đọc từ stderr để có được đầu vào từ termnal.

Như đã đề cập trong câu trả lời khác, các chương trình đọc từ stderr để nhận được câu trả lời tương tác cho một câu hỏi.

Vì người dùng không thể biết trong trường hợp nào chương trình đọc từ stderr, nên việc cố tình ghi dữ liệu vào stderr từ một chương trình khác là vô ích.

Lưu ý rằng ngày nay các chương trình thường cố gắng mở /dev/ttyvà chỉ sử dụng stderr trong trường hợp không hoạt động.

Các chương trình chỉ đọc từ stderr thường chưa bao giờ được sửa đổi kể từ trước năm 1979 và các chương trình như vậy thường chứa các cấu trúc như:

int i 1;

hoặc là

i =* 2;

mà không được chấp nhận bởi trình biên dịch C hiện đại. Kết quả là, rất có thể hôm nay bạn sẽ không tìm thấy một chương trình không bao giờ mở /dev/ttymà chỉ đọc các phản hồi tương tác từ stderr.


Vì vậy, nếu tôi hiểu đúng, vỏ kết nối stderrvới tty khi stdinđược chuyển hướng (thông qua đường ống hoặc phương tiện khác)? Hay chỉ luôn luôn kết nối stderrvới tty?
Draconis

1
Khi bạn đăng nhập, stderr được kết nối với thiết bị đầu cuối đăng nhập của bạn.
schily

2
i =+ 1là C hoàn toàn hợp lệ, và bằng i = (+1). Cấp, trước đây là ứng cử viên tốt đẹp cho cuộc thi C ngầm.
G. Sliepen

1
OK, có thể là nó chỉ tạo ra một cảnh báo. Tôi đã thay đổi mã thành một thứ khác từ C vào năm 1977.
schily

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.