LinuxКак сделать

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

Окно терминала на компьютере с Linux
Фатмавати Ахмад Заенури / Shutterstock.com

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

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

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

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

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

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

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

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

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

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

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

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

Реагирование на трубы и перенаправления

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

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

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

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

  Ls 

ls в окне терминала

  ls |  Кот 

вывод в окно терминала

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

  ls> capture.txt 

ls> capture.txt в окне терминала

  кошка capture.txt 

cat capture.txt в окне терминала

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

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

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

  #! / Bin / Баш

 echo "О попытке получить доступ к файлу, который не существует"
 cat bad-filename.txt 

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

  chmod + x error.sh 

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

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

  ./error.sh 

./error.sh в окне терминала

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

вывод из скрипта error.sh в окне терминала

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

  ./error.sh> capture.txt 

./error.sh> capture.txt в окне терминала

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

  кошка capture.txt 

cat capture.txt в окне терминала

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

содержимое capture.txt в окне терминала

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

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

  1> 

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

  2> 

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

  ./error.sh 2> capture.txt 

./error.sh 2> capture.txt в окне терминала

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

вывод из ./error.sh 2> capture.txt в окне терминала

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

  кошка capture.txt 

cat capture.txt в окне терминала

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

содержимое файла capture.txt в окне терминала

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

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

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

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

./error.sh 1> capture.txt 2> error.txt в окне терминала

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

Вывод ./error.sh в окне терминала

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

  кошка capture.txt 
  cat error.txt 

содержимое capture.txt и 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 , в то же место, куда перенаправляется поток 1, stdout ».

./error.sh> capture.txt 2 &> 1 в окне терминала

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

вывод ./error.sh в окно терминала

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

  кошка capture.txt 

содержимое capture.txt в окне терминала

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

Чтобы перенаправить вывод потока данных и отбросить его без вывода сообщений, направьте вывод в /dev/null .

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

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

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

  #! / Bin / Баш

 если [-t 0];  тогда

   эхо ввода с клавиатуры
 
 еще

   эхо стандартного ввода из трубы или файла
 
 фи 

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

  chmod + x input.sh 

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

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

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

  ./input.sh <dummy.txt 

./input.sh <dummy.txt в окне терминала

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

вывод из скрипта в окне терминала

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

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

кот dummy.txt | ./input.sh в окне терминала

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

вывод скрипта в окне терминала

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

  ./input.sh 

./input.sh в окне терминала

Поток stdin подключен к окну терминала, и скрипт сообщает об этом соответственно.

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

  #! / Bin / Баш

 если [-t 1];  тогда

 echo stdout собирается в окно терминала
 
 еще

 echo stdout перенаправляется или передается по каналу
 
 фи 

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

  chmod + x input.sh 

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

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

  ./output |  Кот 

./output | кот в окне терминала

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

вывод скрипта в окне терминала

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

  ./output.sh> capture.txt 

./output.sh> capture.txt в окне терминала

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

вывод скрипта в окне терминала

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

  кошка захват.ш 

cat capture.sh в окне терминала

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

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

  ./output.sh 

./output.sh в окне терминала

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

вывод скрипта в окне терминала

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

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

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

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

Похожие посты
Как сделать

Как получить возмещение за покупки в iTunes или App Store

Как сделать

Поверхностное перо не работает? Вот как это исправить

Как сделать

Как настроить и использовать Fire TV Recast

Как сделать

Как изменить рингтон по умолчанию на вашем iPhone