Как (и почему) использовать stderr для чтения и письма?
12
Согласно этому ответу schily , lessчитает команды навигации из stderr, если он не может открыть /dev/tty.
Это кажется озадачивающим, поскольку я никогда не видел, чтобы что-то записывало в поток stderr другой программы, и я не знаю, как бы я это сделал.
Какова цель того, чтобы stderr был открыт для чтения и письма? И если это полезно, как мне использовать его в современных системах? (Есть ли какой-то загадочный синтаксис для передачи чего-либо в stderr вместо stdin, например?)
Сначала я был удивлен. Однако после прочтения ответов и небольшого расследования все кажется простым. Итак, вот что я нашел. (в конце концов не было ничего удивительного.)
Перед перенаправлением 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.
Когда вы входите в систему, 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 году.
/dev/tty
см. Этот вопрос .Когда вы входите в систему, stdin, stdout и stderr подключаются к терминалу, с которого вы входите. Точнее, tty открывается обычно, а stdout и stderr являются результатом двух
dup(2)
операций над первым дескриптором файла. Это позволяет читать из stderr для того, чтобы получить информацию от termnal.Как упоминалось в другом ответе, программы читают из stderr, чтобы получить интерактивный ответ на вопрос.
Поскольку пользователь не может знать, при каких обстоятельствах программа читает из stderr, это бесполезная попытка преднамеренно записать данные в stderr из другой программы.
Обратите внимание, что сегодня программы обычно сначала пытаются открыть
/dev/tty
и использовать stderr, только если это не работает.Программы, которые читают только из stderr, обычно никогда не модифицировались до 1979 года, и такие программы обычно содержат такие конструкции, как:
или
которые не принимаются современными компиляторами Си. В результате очень маловероятно, что вы сегодня найдете программу, которая никогда не открывается,
/dev/tty
а скорее читает интерактивные ответы из stderr.источник
stderr
к tty, когдаstdin
перенаправляется (через канал или другими способами)? Или просто всегда подключаетсяstderr
к tty?i =+ 1
совершенно верно C и равноi = (+1)
. Конечно, первый - хороший кандидат на закулисный конкурс C.