Смущены stdin, stdout и stderr? - PullRequest
       96

Смущены stdin, stdout и stderr?

183 голосов
/ 02 августа 2010

Я довольно смущен назначением этих трех файлов.Если мое понимание правильное, stdin - это файл, в который программа записывает свои запросы на выполнение задачи в процессе, stdout - это файл, в который ядро ​​записывает свои выходные данные, и процесс, запрашивающий его, получает информацию изи stderr - это файл, в который вводятся все исключения.При открытии этих файлов, чтобы проверить, действительно ли они происходят, я не нашел ничего, что бы подсказывало это!

Я хотел бы знать, какова цель этих файлов, абсолютно тупой ответ с очень малой технологиейжаргон!

Ответы [ 10 ]

205 голосов
/ 02 августа 2010

Стандартный ввод - это дескриптор файла , который ваш процесс читает для получения информации от вас.

Стандартный вывод - ваш процесс записывает обычную информацию в этот дескриптор файла.

Стандартная ошибка - ваш процесс записывает информацию об ошибке в этот дескриптор файла.

Это настолько глупо, насколько я могу это сделать: -)

Конечно, это в основном по соглашению. Ничто не мешает вам записать информацию об ошибках в стандартный вывод, если хотите. Вы даже можете полностью закрыть три файловых дескриптора и открыть свои собственные файлы для ввода / вывода.

Когда ваш процесс запускается, у него уже должны быть открыты эти маркеры, и он может просто читать и / или записывать их.

По умолчанию они, вероятно, подключены к вашему оконечному устройству (например, /dev/tty), но оболочки позволят вам установить соединения между этими дескрипторами и конкретными файлами и / или устройствами (или даже конвейерами для других процессов) до ваш процесс начинается (некоторые из возможных манипуляций довольно умны).

Примером является:

my_prog <inputfile 2>errorfile | grep XYZ

что будет:

  • создать процесс для my_prog.
  • открыть inputfile в качестве стандартного ввода (дескриптор файла 0).
  • открыть errorfile как стандартную ошибку (дескриптор файла 2).
  • создать другой процесс для grep.
  • присоедините стандартный вывод my_prog к стандартному вводу grep.

Ваш комментарий:

Когда я открываю эти файлы в папке / dev, почему мне никогда не удается увидеть вывод запущенного процесса?

Это потому что они не нормальные файлы. В то время как UNIX представляет все как файл в файловой системе где-то, это не делает это на самых низких уровнях. Большинство файлов в иерархии /dev являются символьными или блочными устройствами, фактически драйвером устройства. У них нет размера, но у них есть старший и младший номер устройства.

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

То же самое верно для файловой системы Linux /proc. Это не настоящие файлы, это просто строго контролируемые шлюзы с информацией о ядре.

49 голосов
/ 02 августа 2010

Было бы правильнее сказать, что stdin, stdout и stderr скорее являются "потоками ввода / вывода" чем файлы. Как вы заметили, эти сущности не живут в файловой системе. Но Философия Unix в том, что касается ввода / вывода, заключается в том, что «все это файл». На практике, это действительно означает, что вы можете использовать те же библиотечные функции и интерфейсы (printf, scanf, read, write, select и т. Д.), Не беспокоясь о том, является ли поток ввода-вывода подключен к клавиатуре, файлу диска, сокету, каналу или некоторой другой абстракции ввода / вывода.

Большинству программ нужно читать ошибки ввода, записи и журнала, поэтому stdin, stdout, и stderr предопределены для вас для удобства программирования. Это только соглашение и не применяется операционной системой.

33 голосов
/ 09 апреля 2018

В качестве дополнения к ответам, приведенным выше, ниже приводится сводная информация о перенаправлениях: Redirections cheatsheet

РЕДАКТИРОВАТЬ: этот рисунок не совсем правильный, но я не уверен, почему ...

На рисунке написано, что 2> & 1 имеет тот же эффект, что и &> однако

ls Documents ABC > dirlist 2>&1
#does not give the same output as 
ls Documents ABC > dirlist &>
22 голосов
/ 02 августа 2010

Боюсь, ваше понимание полностью отсталое.:)

Подумайте о «стандартном входе», «стандартном выходе» и «стандартной ошибке» с точки зрения программы *1003*, а не с точки зрения ядра.

КогдаПрограмма должна распечатать вывод, обычно она печатает в «стандартный формат».Программа обычно печатает вывод на стандартный вывод с помощью printf, который печатает ТОЛЬКО на стандартный вывод.

Когда программе необходимо напечатать информацию об ошибке (не обязательно исключения, это конструкция языка программирования, наложенная нанамного более высокий уровень), он обычно печатает до «стандартной ошибки».Обычно это происходит с fprintf, который принимает файловый поток для использования при печати.Файловым потоком может быть любой файл, открытый для записи: стандартный вывод, стандартная ошибка или любой другой файл, открытый с помощью fopen или fdopen.

«стандартный вход» используется, когда файл необходимдля чтения ввода, используя fread или fgets, или getchar.

Любой из этих файлов может быть легко перенаправлен из оболочки, например:

cat /etc/passwd > /tmp/out     # redirect cat's standard out to /tmp/foo
cat /nonexistant 2> /tmp/err   # redirect cat's standard error to /tmp/error
cat < /etc/passwd              # redirect cat's standard input to /etc/passwd

Или вся энчилада:

cat < /etc/passwd > /tmp/out 2> /tmp/err

Есть два важных предостережения: во-первых, «стандартный вход», «стандартный выход» и «стандартная ошибка» - это просто соглашение.Это очень сильное соглашение, но все это просто соглашение, что очень приятно иметь возможность запускать программы, подобные этой: grep echo /etc/services | awk '{print $2;}' | sort и иметь стандартные выходные данные каждой программы, подключенные к стандартному входуследующая программа в конвейере.

Во-вторых, я дал стандартные функции ISO C для работы с файловыми потоками (FILE * объекты) - на уровне ядра, это все файловые дескрипторы (int ссылки на таблицу файлов) и многие операции более низкого уровня, такие как read и write, которые не выполняют удачную буферизацию функций ISO C.Я решил сделать это простым и использовать более легкие функции, но я все же подумал, что вы должны знать альтернативы.:)

7 голосов
/ 02 августа 2010

STDIN

Считывает ввод через консоль (например, ввод с клавиатуры). Используется в C с scanf

scanf(<formatstring>,<pointer to storage> ...);

стандартный вывод

Выводит вывод на консоль. Используется в C с printf

printf(<string>, <values to print> ...);

STDERR

Выводит сообщение об ошибке на консоль. Используется в C с fprintf

fprintf(stderr, <string>, <values to print> ...);

Перенаправление

Источник для stdin может быть перенаправлен. Например, вместо ввода с клавиатуры это может быть файл (echo < file.txt) или другая программа (ps | grep <userid>).

Направления для stdout, stderr также могут быть перенаправлены. Например, стандартный вывод может быть перенаправлен в файл: ls . > ls-output.txt, в этом случае вывод записывается в файл ls-output.txt. Stderr может быть перенаправлен с 2>.

5 голосов
/ 20 января 2017

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

Он также должен использоваться для информативных сообщений, предназначенных для пользователя, выполняющего команду, а не для любых потенциальных потребителей данных в потоке (т. Е. Если вы запускаете оболочку из нескольких команд, вам не нужны информативные сообщения).например, «получение элемента 30 из 42424» должно появиться на stdout, поскольку это может сбить с толку потребителя, но вы все равно можете захотеть, чтобы пользователь их увидел.

См. this для исторического обоснования:

"Все программы помещали диагностику на стандартный вывод. Это всегда вызывало проблемы, когда вывод перенаправлялся в файл, но становилось недопустимым, когда вывод отправлялся в ничего не подозревающий процесс. Тем не менее, нежеланиеНарушая простоту модели стандартного ввода-вывода, люди терпели такое положение вещей до версии 6. Вскоре после этого Деннис Ритчи разорвал узел Гордиана, введя стандартный файл ошибок. Этого было недостаточно. С помощью конвейеров диагностика могла быть получена излюбой из снесколько программ, работающих одновременно.Диагностика должна была идентифицировать себя. "

3 голосов
/ 27 июля 2014

Использование ps -aux показывает текущие процессы, все из которых перечислены в / proc / as / proc / (pid) /, вызывая cat / proc / (pid) / fd / 0, он печатает все, что найдено в стандартный вывод этого процесса, я думаю. Так что, возможно,

/ proc / (pid) / fd / 0 - Стандартный выходной файл
/ proc / (pid) / fd / 1 - стандартный входной файл
/ proc / (pid) / fd / 2 - стандартный файл ошибок

например my terminal window

Но это работало только для / bin / bash, другие процессы обычно не имели ничего в 0, но многие имели ошибки, записанные в 2

2 голосов
/ 17 июля 2018

Для получения достоверной информации об этих файлах посмотрите справочные страницы, запустите команду на своем терминале.

$ man stdout 

Но для простого ответа каждый файл предназначен для:

stdout для потока

stdin для ввода потока

stderr для печати ошибок или сообщений журнала.

Каждая программа unix имеет каждый из этих потоков.

2 голосов
/ 13 февраля 2018

stderr не будет выполнять буферизацию IO Cache, поэтому, если нашему приложению нужно распечатать критическую информацию о сообщении (некоторые ошибки, исключения) в консоль или в файл, используйте ее, где в качестве stdout используется для печати общих данных журнала, поскольку используется буферизация IO Cache вероятность того, что перед записью наших сообщений в файл приложение может закрыться, оставив отладочный комплекс

0 голосов
/ 28 сентября 2017

Файл со связанной буферизацией называется потоком и объявляется как указатель на FILE определенного типа. Функция fopen () создает определенные описательные данные для потока и возвращает указатель для обозначения потока во всех дальнейших транзакциях. Обычно есть три открытых потока с постоянными указателями, объявленными в заголовке и связанными со стандартными открытыми файлами. При запуске программы три потока предварительно определены и не требуют явного открытия: стандартный ввод (для чтения обычного ввода), стандартный вывод (для записи обычного вывода) и стандартная ошибка (для записи диагностического вывода). При открытии стандартный поток ошибок не полностью буферизуется; стандартные входные и стандартные выходные потоки полностью буферизуются тогда и только тогда, когда можно определить, что поток не относится к интерактивному устройству

https://www.mkssoftware.com/docs/man5/stdio.5.asp

...