Как (и почему) использовать stderr для чтения и письма?

12

Согласно этому ответу schily , lessчитает команды навигации из stderr, если он не может открыть /dev/tty.

Это кажется озадачивающим, поскольку я никогда не видел, чтобы что-то записывало в поток stderr другой программы, и я не знаю, как бы я это сделал.

Какова цель того, чтобы stderr был открыт для чтения и письма? И если это полезно, как мне использовать его в современных системах? (Есть ли какой-то загадочный синтаксис для передачи чего-либо в stderr вместо stdin, например?)

Draconis
источник

Ответы:

7

Сначала я был удивлен. Однако после прочтения ответов и небольшого расследования все кажется простым. Итак, вот что я нашел. (в конце концов не было ничего удивительного.)

Перед перенаправлением stdin, stdout и stderr, как и ожидалось, подключены к одному и тому же устройству.

#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

Поэтому после большинства перенаправлений (то есть, если stderr) не перенаправляется. stderr все еще подключен к терминалу. Поэтому его можно прочитать, чтобы получить ввод с клавиатуры.

Единственное, что останавливает файлы, используемые в неожиданном направлении, - это соглашение, и каналы являются однонаправленными.

Другой пример, попробуйте:

cat | less

Это идет не так после страницы, когда lessпытается прочитать терминал (это не удивительно, так же как catи чтение терминала).

/dev/ttyболее загадочным, это не ссылка на /proc/self.

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

Посмотрите, какие отношения существуют между моим текущим управляющим терминалом и `/ dev / tty`? для объяснения. Спасибо @StephenKitt за ссылку.

Ctrl-Alt-Делор
источник
По поводу /dev/ttyсм. Этот вопрос .
Стивен Китт
6

Когда вы входите в систему, stdin, stdout и stderr подключаются к терминалу, с которого вы входите. Точнее, tty открывается обычно, а stdout и stderr являются результатом двух dup(2)операций над первым дескриптором файла. Это позволяет читать из stderr для того, чтобы получить информацию от termnal.

Как упоминалось в другом ответе, программы читают из stderr, чтобы получить интерактивный ответ на вопрос.

Поскольку пользователь не может знать, при каких обстоятельствах программа читает из stderr, это бесполезная попытка преднамеренно записать данные в stderr из другой программы.

Обратите внимание, что сегодня программы обычно сначала пытаются открыть /dev/ttyи использовать stderr, только если это не работает.

Программы, которые читают только из stderr, обычно никогда не модифицировались до 1979 года, и такие программы обычно содержат такие конструкции, как:

int i 1;

или

i =* 2;

которые не принимаются современными компиляторами Си. В результате очень маловероятно, что вы сегодня найдете программу, которая никогда не открывается, /dev/ttyа скорее читает интерактивные ответы из stderr.

Шили
источник
Так что, если я правильно понимаю, оболочка подключается stderrк tty, когда stdinперенаправляется (через канал или другими способами)? Или просто всегда подключается stderrк tty?
Драконис
1
Когда вы входите в систему, stderr подключается к вашему терминалу входа.
Шили
2
i =+ 1совершенно верно C и равно i = (+1). Конечно, первый - хороший кандидат на закулисный конкурс C.
Г. Слипен
1
ОК, может быть, это просто создает предупреждение. Я изменил код на что-то еще с C в 1977 году.
schily