Что такое stdin, stdout и stderr в Linux?

stdin, stdoutи stderr- это три потока данных, которые создаются при запуске команды Linux. Вы можете использовать их, чтобы определить, передаются ли ваши скрипты по конвейеру или перенаправляются. Мы покажем вам, как это сделать.

Потоки объединяются в две точки

Как только вы начинаете , чтобы узнать о Linux и Unix-подобных операционных систем, вы столкнетесь с условиями stdin, stdoutи stederr. Это три стандартных потока, которые устанавливаются при выполнении команды Linux. В вычислениях поток - это то, что может передавать данные. В случае этих потоков эти данные являются текстовыми.

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

Стандартные потоки Linux

В Linux  stdinэто стандартный поток ввода. Это принимает текст в качестве ввода. Текстовый вывод команды в оболочку доставляется через stdout(стандартный выходной ) поток. Сообщения об ошибках от команды отправляются через stderrпоток (стандартная ошибка).

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

Потоки обрабатываются как файлы

Потоки в Linux - как и почти все остальное - обрабатываются как файлы. Вы можете читать текст из файла и записывать текст в файл. Оба эти действия включают поток данных. Так что концепция обработки потока данных в виде файла не так уж и сложна.

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

Эти значения всегда используются stdin, stdout,и stderr:

  • 0 : стандартный ввод
  • 1 : стандартный вывод
  • 2 : stderr

Реакция на каналы и перенаправления

Чтобы облегчить кому-то знакомство с предметом, распространенной техникой является преподавание упрощенной версии темы. Например, в грамматике нам говорят, что правило - «I до E, кроме C.» Но на самом деле исключений из этого правила больше, чем случаев, которые ему подчиняются.

В том же духе, когда речь идет о stdin, stdoutи stderr это удобно щеголять Принятая аксиому о том , что процесс не знает и не заботится , где прерываются , его три стандартных потока. Должен ли процесс заботиться о том, идет ли его вывод на терминал или перенаправляется в файл? Может ли он даже определить, поступает ли его ввод с клавиатуры или поступает в него из другого процесса?

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

Мы можем очень легко увидеть это изменение в поведении. Попробуйте эти две команды:

ls

ls | Кот

Команда lsведет себя иначе, если ее output ( stdout) передается другой команде. Это  lsпереключение на вывод в один столбец, а не преобразование, выполняемое cat. И lsделает то же самое, если его вывод перенаправляется:

ls> capture.txt

cat capture.txt

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

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

Введите следующий текст в редактор и сохраните его в файл с именем error.sh.

#! / bin / bash echo "О попытке доступа к несуществующему файлу" cat bad-filename.txt

Сделайте скрипт исполняемым с помощью этой команды:

chmod + x error.sh

Первая строка скрипта выводит текст в окно терминала через  stdoutпоток. Вторая строка пытается получить доступ к несуществующему файлу. Это сгенерирует сообщение об ошибке, которое будет доставлено через stderr.

Запустите сценарий с помощью этой команды:

./error.sh

Мы видим, что оба потока вывода stdoutи stderr, были отображены в окнах терминала.

Попробуем перенаправить вывод в файл:

./error.sh> capture.txt

Сообщение об ошибке, доставленное через, stderrпо-прежнему отправляется в окно терминала. Мы можем проверить содержимое файла, чтобы увидеть, stdout попал ли вывод в файл.

cat capture.txt

Выходные данные stdinбыли перенаправлены в файл, как и ожидалось.

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

Чтобы явно перенаправить  stdout, используйте эту инструкцию перенаправления:

1>

Чтобы явно перенаправить  stderr, используйте эту инструкцию перенаправления:

2>

Давайте попробуем снова провести наш тест, и на этот раз мы будем использовать 2>:

./error.sh 2> capture.txt

Сообщение об ошибке перенаправляется, и stdoutechoсообщение отправляется в окно терминала:

Посмотрим, что находится в файле capture.txt.

cat capture.txt

Как stderrи ожидалось, сообщение находится в файле capture.txt.

Перенаправление как stdout, так и stderr

Конечно, если мы можем перенаправить один stdoutили stderrдругой файл независимо друг от друга, мы должны иметь возможность перенаправить их обоих одновременно в два разных файла?

Да мы можем. Эта команда будет направлять stdoutв файл с именем capture.txt и stderrв файл с именем error.txt.

./error.sh 1> capture.txt 2> error.txt

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

Проверим содержимое каждого файла:

cat capture.txt
cat error.txt

Перенаправление stdout и stderr в один файл

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

Мы можем добиться этого с помощью следующей команды:

./error.sh> capture.txt 2> & 1

Давайте разберемся с этим.

  • ./error.sh : Запускает файл сценария error.sh.
  • > capture.txt : перенаправляет stdoutпоток в файл capture.txt. >это сокращение для 1>.
  • 2> & 1 : здесь используется инструкция перенаправления &>. Эта инструкция позволяет вам указать оболочке, чтобы один поток попал в то же место назначения, что и другой поток. В этом случае мы говорим «перенаправить поток 2, stderrв то же место назначения, куда stdoutперенаправляется поток 1 ».

Нет видимого вывода. Это обнадеживает.

Давайте проверим файл capture.txt и посмотрим, что в нем.

cat capture.txt

Как stdoutи stderrпотоки были перенаправлены в один файл назначения.

Чтобы вывод потока перенаправлялся и автоматически отбрасывался, направьте вывод в /dev/null.

Обнаружение перенаправления в сценарии

Мы обсудили, как команда может определить, перенаправляется ли какой-либо из потоков, и может соответствующим образом изменить свое поведение. Можем ли мы сделать это в наших собственных сценариях? Да мы можем. И это очень простой метод для понимания и применения.

Введите следующий текст в редактор и сохраните его как input.sh.

#! / bin / bash если [-t 0]; затем echo stdin, поступающий с клавиатуры, иначе echo stdin, исходящий из канала или файла fi

Используйте следующую команду, чтобы сделать его исполняемым:

chmod + x input.sh

Самое интересное - это тест в квадратных скобках. Опция -t(терминал) возвращает истину (0), если файл, связанный с файловым дескриптором, завершается в окне терминала. Мы использовали файловый дескриптор 0 в качестве аргумента теста, который представляет   stdin.

Если stdinон подключен к окну терминала, тест подтвердится. Если stdinон подключен к файлу или каналу, тест не пройден.

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

./input.sh <dummy.txt

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

Это было с перенаправлением файлов, давайте попробуем с конвейером.

кот dummy.txt | ./input.sh

Сценарий распознает, что его ввод передается по конвейеру. Или, точнее, еще раз распознает, что stdinпоток не связан с окном терминала.

Запустим скрипт без каналов и редиректов.

./input.sh

stdinПоток связан с окна терминала, и сценарий сообщает об этом соответствующим образом .

Чтобы проверить то же самое с выходным потоком, нам нужен новый скрипт. Введите в редактор следующее и сохраните его как output.sh.

#! / bin / bash если [-t 1]; тогда echo stdout переходит в окно терминала, иначе echo stdout перенаправляется или передается по каналу fi

Используйте следующую команду, чтобы сделать его исполняемым:

chmod + x input.sh

Единственное существенное изменение в этом скрипте - тест в квадратных скобках. Мы используем цифру 1 для обозначения файлового дескриптора stdout.

Давай попробуем. Мы пропустим вывод через cat.

./output | Кот

Сценарий распознает, что его вывод не идет напрямую в окно терминала.

Мы также можем протестировать скрипт, перенаправив вывод в файл.

./output.sh> capture.txt

В окне терминала нет вывода, мы молча возвращаемся в командную строку. Как и следовало ожидать.

Мы можем заглянуть внутрь файла capture.txt, чтобы увидеть, что было захвачено. Для этого используйте следующую команду.

кошка capture.sh

Опять же, простой тест в нашем скрипте обнаруживает, что stdoutпоток не отправляется непосредственно в окно терминала.

Если мы запустим сценарий без каких-либо каналов или перенаправлений, он должен обнаружить, что stdoutон доставляется непосредственно в окно терминала.

./output.sh

И это именно то, что мы видим.

Потоки сознания

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

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

Как обычно бывает, чем больше знаний, тем больше возможностей.