Jak (i ​​dlaczego) używać stderr zarówno do czytania, jak i pisania?

12

Według tej odpowiedzi przez Schily , lessodczytuje polecenia nawigacyjne ze standardowego wyjścia błędów, jeśli nie jest w stanie otworzyć /dev/tty.

To wydaje się zagadkowe, ponieważ nigdy nie widziałem, aby cokolwiek zapisywało w strumieniu stderr innego programu, i nie wiem, jak bym to osiągnął.

W jakim celu stderr jest otwarty na czytanie i pisanie? A jeśli jest to przydatne, jak mogę z niego korzystać w nowoczesnych systemach? (Czy jest na przykład jakaś tajemnicza składnia pozwalająca przesłać coś do stderr zamiast stdin, na przykład?)

Draconis
źródło

Odpowiedzi:

7

Na początku byłem zaskoczony. Jednak po przeczytaniu odpowiedzi i przeprowadzeniu krótkiego dochodzenia wydaje się to proste. Oto co znalazłem. (w końcu nie było niespodzianki).

Przed przekierowaniem stdin, stdout i stderr są zgodnie z oczekiwaniami podłączone do tego samego urządzenia.

#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

Dlatego po większości przekierowań (czyli jeśli stderr) nie jest przekierowywany. stderr jest nadal podłączony do terminala. Dlatego można go odczytać, aby uzyskać dane z klawiatury.

Jedyną rzeczą, która powstrzymuje pliki używane w nieoczekiwanym kierunku, jest konwencja, a potoki są jednokierunkowe.

Inny przykład:

cat | less

To idzie źle po stronie, gdy lesspróbuje odczytać terminal (nie jest to niespodzianką, podobnie jak catczytanie terminalu).

/dev/ttyjest bardziej tajemniczy, to nie jest link do /proc/self.

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

Zobacz, jakie są relacje między moim obecnym terminalem sterującym a `/ dev / tty`? do eksploracji. Dzięki @StephenKitt za link.

ctrl-alt-delor
źródło
Jeśli chodzi o /dev/tty, zobacz to pytanie .
Stephen Kitt
6

Kiedy się logujesz, stdin, stdout i stderr są podłączone do terminala, z którego się logujesz. Aby być bardziej dokładnym, tty jest typowo otwierane, a stdout i stderr są wynikiem dwóch dup(2)operacji na pierwszym deskryptorze pliku. Pozwala to na odczyt ze stderr w celu uzyskania danych wejściowych z terminala.

Jak wspomniano w drugiej odpowiedzi, programy czytają ze stderr, aby uzyskać interaktywną odpowiedź na pytanie.

Ponieważ użytkownik nie może wiedzieć, w jakich okolicznościach program odczytuje stderr, jest to bezużyteczna próba celowego zapisu danych do stderr z innego programu.

Zauważ, że dzisiaj programy zwykle najpierw próbują otworzyć /dev/ttyi używać stderr tylko w przypadku, gdy to nie działa.

Programy, które tylko czytają ze stderr, zwykle nigdy nie były modyfikowane od 1979 roku i takie programy zwykle zawierają konstrukcje takie jak:

int i 1;

lub

i =* 2;

które nie są akceptowane przez nowoczesne kompilatory C. W rezultacie jest mało prawdopodobne, abyś dzisiaj znalazł program, który nigdy się nie otwiera, /dev/ttya raczej czyta interaktywne odpowiedzi ze stderr.

schily
źródło
Więc jeśli dobrze rozumiem, powłoka łączy stderrsię z tty, kiedy stdinjest przekierowywana (przez potok lub w inny sposób)? Czy po prostu zawsze łączy stderrsię z tty?
Draconis
1
Po zalogowaniu stderr jest podłączony do terminala logowania.
schily
2
i =+ 1ma idealnie poprawne C i jest równe i = (+1). To prawda, że ​​ten pierwszy jest dobrym kandydatem do podstępnego konkursu C.
G. Sliepen
1
OK, może być tak, że po prostu tworzy ostrzeżenie. Zmieniłem kod na coś innego niż C w 1977 r.
schily
1
Wydaje się, że zdaję sobie sprawę z kilku powłok, ponieważ ja nie wiem o co najmniej jednej muszli, który odczytuje z innych niż standardowe wejście . (-:
JdeBP