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?)
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.
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.
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.
/dev/tty
, zobacz to pytanie .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/tty
i 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:
lub
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/tty
a raczej czyta interaktywne odpowiedzi ze stderr.źródło
stderr
się z tty, kiedystdin
jest przekierowywana (przez potok lub w inny sposób)? Czy po prostu zawsze łączystderr
się z tty?i =+ 1
ma idealnie poprawne C i jest równei = (+1)
. To prawda, że ten pierwszy jest dobrym kandydatem do podstępnego konkursu C.