Stdin linux что это
Фундаментальные основы Linux. Часть IV. Программные каналы и команды
Оригинал: Linux Fundamentals
Автор: Paul Cobbaut
Дата публикации: 16 октября 2014 г.
Перевод: А.Панин
Дата перевода: 15 декабря 2014 г.
Глава 16. Перенаправление потоков ввода/вывода
В данной главе даются пояснения относительно перенаправления стандартных потоков ввода, вывода и ошибок.
Потоки данных stdin, stdout и stderr
Командная оболочка bash поддерживает три типа базовых потоков данных; она принимает данные из стандартного потока ввода stdin (поток 0 ), отправляет данные в стандартный поток вывода stdout (поток 1 ), а также отправляет сообщения об ошибках в стандартный поток ошибок stderr (поток 2 ).
Приведенная ниже иллюстрация является графической интерпретацией этих трех потоков данных.
В следующем разделе будет рассказано о том, как осуществляется перенаправление упомянутых потоков данных.
Перенаправление стандартного потока вывода
Операция перенаправления потока данных stdout (>)
командная оболочка будет рассматривать только два аргумента (echo = аргумент 0, привет = аргумент 1). Описание операции перенаправления потока данных удаляется перед началом подсчета количества аргументов.
Содержимое выходного файла удаляется
Параметр командной оболочки noclobber
Нейтрализация влияния параметра командной оболочки noclobber
Перенаправление стандартного потока ошибок
Операция перенаправления потока данных stderr (2>)
Операция перенаправления нескольких потоков данных 2>&1
позволяет перенаправить только данные из стандартного потока вывода в файл dirlist, так как с помощью данной команды осуществляется копирование дескриптора стандартного потока вывода в дескриптор стандартного потока ошибок перед тем, как стандартный поток вывода перенаправляется в файл dirlist.
Перенаправление стандартного потока вывода и программные каналы
Объединение стандартных потоков вывода stdout и ошибок stderr
Перенаправление стандартного потока ввода
Операция перенаправления потока данных stdin ( стандартного потока ввода stdin осуществляется с помощью оператора here document (иногда называемая структурой here-is-document) является механизмом для ввода данных до момента обнаружения определенной последовательности символов (обычно EOF). Маркер EOF может быть либо введен вручную, либо вставлен автоматически при нажатии комбинации клавиш Ctrl-D.
Структура here string может использоваться для непосредственной передачи строк команде. При использовании данной структуры достигается такой же эффект, как и при использовании команды echo строка | команда (но вы сможете избежать создания одного дополнительного процесса).
Для получения дополнительной информации об алгоритме base64 следует обратиться к стандарту rfc 3548.
Неоднозначное перенаправление потоков ввода/вывода
Быстрая очистка содержимого файла
Практическое задание: перенаправление потоков ввода/вывода
3. Какой из символов представляет параметр noclobber в списке всех параметров командной оболочки.
6. Создайте файл, содержащий имена пяти людей. Используйте команду cat и механизм перенаправления потоков ввода/вывода для создания файла, а также структуру here document для завершения ввода.
Корректная процедура выполнения практического задания: перенаправление потоков ввода/вывода
3. Какой из символов представляет параметр noclobber в списке всех параметров командной оболочки.
6. Создайте файл, содержащий имена пяти людей. Используйте команду cat и механизм перенаправления потоков ввода/вывода для создания файла, а также структуру here document для завершения ввода.
Что такое stdin, stdout и stderr в Linux?
Потоки объединяют две точки
Потоки данных, как и потоки воды, имеют два конца. У них есть источник и отток. Какую бы команду Linux вы не использовали, она обеспечивает один конец каждого потока. Другой конец определяется оболочкой, которая запустила команду. Этот конец будет связан с окном терминала, подключен к каналу или перенаправлен в файл или другую команду в соответствии с командной строкой, которая запустила команду.
Стандартные потоки Linux
В Linux стандартный ввод — стандартный поток ввода. Это принимает текст в качестве входных данных. Вывод текста из команды в оболочку осуществляется через поток stdout (standard out). Сообщения об ошибках из команды отправляются через поток stderr (стандартная ошибка).
Потоки обрабатываются как файлы
Потоки в Linux — как и почти все остальное — рассматриваются как файлы. Вы можете читать текст из файла, и вы можете написать текст в файл. Оба эти действия связаны с потоком данных. Таким образом, концепция обработки потока данных как файла не так уж и сложна.
Каждому файлу, связанному с процессом, присваивается уникальный номер для его идентификации. Это называется дескриптором файла. Всякий раз, когда требуется выполнить действие над файлом, дескриптор файла используется для идентификации файла.
Реагирование на трубы и перенаправления
Чтобы облегчить чье-то знакомство с предметом, общепринятым методом является обучение упрощенной версии темы. Например, в грамматике нам говорят, что правило «Я до E, кроме C». Но на самом деле, существует больше исключений из этого правила, чем случаев, которые ему подчиняются.
На самом деле, процесс знает — или, по крайней мере, может узнать, выберет ли он проверку — и может соответствующим образом изменить свое поведение, если автор программного обеспечения решил добавить эту функцию.
Мы можем увидеть это изменение в поведении очень легко. Попробуйте эти две команды:
capture.txt в окне терминала» width=»646″ height=»57″ svg+xml,%3Csvg%20xmlns=’http://www.w3.org/2000/svg’%20viewBox=’0%200%20646%2057’%3E%3C/svg%3E» data-lazy-src=»https://gadgetshelp.com/wp-content/uploads/images/htg/content/uploads/2019/08/x41.png.pagespeed.gp+jp+jw+pj+ws+js+rj+rp+rw+ri+cp+md.ic.hyUFiptU3o.png»/>
Перенаправление stdout и stderr
Введите следующий текст в редактор и сохраните его в файл с именем error.sh.
Сделайте скрипт исполняемым с помощью этой команды:
Запустите скрипт с помощью этой команды:
Попробуем перенаправить вывод в файл:
capture.txt в окне терминала» width=»646″ height=»57″ svg+xml,%3Csvg%20xmlns=’http://www.w3.org/2000/svg’%20viewBox=’0%200%20646%2057’%3E%3C/svg%3E» data-lazy-src=»https://gadgetshelp.com/wp-content/uploads/images/htg/content/uploads/2019/08/x3.png.pagespeed.gp+jp+jw+pj+ws+js+rj+rp+rw+ri+cp+md.ic.EqpbNlGg0r.png»/>
Вывод из stdin был перенаправлен в файл, как и ожидалось.
Символ перенаправления > работает с stdout по умолчанию. Вы можете использовать один из числовых файловых дескрипторов, чтобы указать, какой стандартный поток вывода вы хотите перенаправить.
Давайте попробуем провести наш тест еще раз, и на этот раз мы будем использовать 2> :
capture.txt в окне терминала» width=»646″ height=»57″ svg+xml,%3Csvg%20xmlns=’http://www.w3.org/2000/svg’%20viewBox=’0%200%20646%2057’%3E%3C/svg%3E» data-lazy-src=»https://gadgetshelp.com/wp-content/uploads/images/htg/content/uploads/2019/08/x17.png.pagespeed.gp+jp+jw+pj+ws+js+rj+rp+rw+ri+cp+md.ic.JgI_SRjATy.png»/>
Сообщение об ошибке перенаправляется, и echo сообщение stdout отправляется в окно терминала:
capture.txt в окне терминала» width=»646″ height=»97″ svg+xml,%3Csvg%20xmlns=’http://www.w3.org/2000/svg’%20viewBox=’0%200%20646%2097’%3E%3C/svg%3E» data-lazy-src=»https://gadgetshelp.com/wp-content/uploads/images/htg/content/uploads/2019/08/x18.png.pagespeed.gp+jp+jw+pj+ws+js+rj+rp+rw+ri+cp+md.ic.DT9oiWeFHK.png»/>
Давайте посмотрим, что находится в файле capture.txt.
Сообщение stderr находится в capture.txt, как и ожидалось.
Перенаправление как stdout, так и stderr
Конечно, если мы можем перенаправить либо stdout либо stderr в файл независимо друг от друга, мы должны быть в состоянии перенаправить их одновременно в два разных файла?
Да мы можем. Эта команда направит стандартный stdout в файл с именем capture.txt, а стандартный stderr — в файл с именем error.txt.
capture.txt 2> error.txt в окне терминала» width=»646″ height=»57″ svg+xml,%3Csvg%20xmlns=’http://www.w3.org/2000/svg’%20viewBox=’0%200%20646%2057’%3E%3C/svg%3E» data-lazy-src=»https://gadgetshelp.com/wp-content/uploads/images/htg/content/uploads/2019/08/x20.png.pagespeed.gp+jp+jw+pj+ws+js+rj+rp+rw+ri+cp+md.ic.tfJGMMFL3p.png»/>
Поскольку оба потока вывода — стандартный вывод и стандартная ошибка — перенаправляются в файлы, в окне терминала отсутствует видимый вывод. Мы возвращаемся к командной строке, как будто ничего не произошло.
Давайте проверим содержимое каждого файла:
Перенаправление stdout и stderr в один файл
Это здорово, у нас есть каждый из стандартных выходных потоков, идущих в свой отдельный выделенный файл. Единственная другая комбинация, которую мы можем сделать, это отправить и stdout и stderr в один и тот же файл.
Мы можем добиться этого с помощью следующей команды:
Давайте разберемся с этим.
capture.txt 2 &> 1 в окне терминала» width=»646″ height=»57″ svg+xml,%3Csvg%20xmlns=’http://www.w3.org/2000/svg’%20viewBox=’0%200%20646%2057’%3E%3C/svg%3E» data-lazy-src=»https://gadgetshelp.com/wp-content/uploads/images/htg/content/uploads/2019/08/x23.png.pagespeed.gp+jp+jw+pj+ws+js+rj+rp+rw+ri+cp+md.ic.E9Im1_c4LS.png»/>
Нет видимого вывода. Это обнадеживает.
Давайте проверим файл capture.txt и посмотрим, что в нем.
Потоки stdout и stderr были перенаправлены в один файл назначения.
Обнаружение перенаправления в скрипте
Мы обсудили, как команда может обнаружить, перенаправлен ли какой-либо из потоков, и может соответствующим образом изменить свое поведение. Можем ли мы сделать это в наших собственных сценариях? Да мы можем. И это очень простая техника для понимания и применения.
Введите следующий текст в редактор и сохраните его как input.sh.
Используйте следующую команду, чтобы сделать его исполняемым:
Если stdin подключен к окну терминала, тест подтвердится. Если stdin подключен к файлу или каналу, тест не пройден.
Мы можем использовать любой удобный текстовый файл для генерации ввода в скрипт. Здесь мы используем файл с именем dummy.txt.
Вывод показывает, что скрипт распознает, что ввод не с клавиатуры, а с файла. Если вы захотите, вы можете соответствующим образом изменить поведение вашего скрипта.
Это было с перенаправлением файла, давайте попробуем это с каналом.
Сценарий распознает, что его вход передается по каналу. Точнее, он еще раз распознает, что поток stdin не подключен к окну терминала.
Давайте запустим скрипт без каналов и перенаправлений.
Поток stdin подключен к окну терминала, и скрипт сообщает об этом соответственно.
Чтобы проверить то же самое с выходным потоком, нам нужен новый скрипт. Введите следующее в редактор и сохраните его как output.sh.
Используйте следующую команду, чтобы сделать его исполняемым:
Скрипт распознает, что его вывод не идет прямо в окно терминала.
Мы также можем протестировать скрипт, перенаправив вывод в файл.
capture.txt в окне терминала» width=»646″ height=»57″ svg+xml,%3Csvg%20xmlns=’http://www.w3.org/2000/svg’%20viewBox=’0%200%20646%2057’%3E%3C/svg%3E» data-lazy-src=»https://gadgetshelp.com/wp-content/uploads/images/htg/content/uploads/2019/08/x34.png.pagespeed.gp+jp+jw+pj+ws+js+rj+rp+rw+ri+cp+md.ic.df5fttcFac.png»/>
Нет вывода в окно терминала, мы молча возвращаемся в командную строку. Как и следовало ожидать.
Мы можем заглянуть внутрь файла capture.txt, чтобы увидеть, что было захвачено. Используйте следующую команду, чтобы сделать это.
Опять же, простой тест в нашем скрипте обнаруживает, что поток stdout не отправляется непосредственно в окно терминала.
Если мы запустим скрипт без каких-либо каналов или перенаправлений, он должен обнаружить, что стандартный stdout доставляется непосредственно в окно терминала.
И это именно то, что мы видим.
Потоки Сознания
Знание того, как определить, подключены ли ваши скрипты к окну терминала, каналу или перенаправлены, позволяет соответствующим образом настроить их поведение.
Регистрация и диагностический вывод могут быть более или менее подробными, в зависимости от того, идет ли речь об экране или в файл. Сообщения об ошибках могут быть записаны в файл, отличный от нормального вывода программы.
Как обычно, больше знаний приносит больше вариантов.
Потоки данных
Статья посвящена работой с потоками данных в bash. Я постарался написать ее наиболее доступным и простым языком, чтобы было понятно даже новичкам в Linux.
В одной из моих статей мы рассматривали запись звука в файл с помощью команды:
Эта команда читает файл (устройство) /dev/audio с помощью команды cat и перенаправляет информацию из него в файл /tmp/my.sound (с помощью оператора >).
У каждой программы существует 3 системных потока: stdout, stderr, stdin.
stdout
Стандартный поток вывода данных для программ. Например, когда мы пишем команду ls, то список папок и файлов она выводит именно в этот поток, который отображается у нас в консоли:
stderr
Поток вывода ошибок. Если программа не смогла сделать все как надо — она пишет именно в этот поток. Например, когда rm пытается удалить несуществующий файл:
$ rm example.txt
rm: example.txt: No such file or directory
stdin
Поток ввода данных. А вот это довольно интересный и удобный поток. Например, его использует вэб-сервер, когда просит интерпретаторы выполнить скрипты через CGI. Мы тоже можем попробовать:
В этом примере мы встретили оператор перенаправления потока вывода. Мы остановимся на нем позже.
Перенаправление потоков
Для начала рассмотрим перенаправление потоков в файлы, устройства и другие потоки.
В этом примере мы направили stdout команды ls в файл 1.txt. Читаем его:
Да, все успешно записалось.
Теперь попробуем направить stderr команды rm:
Здесь мы использовали номер потока stderr (2). По умолчанию оператор > перенаправляет поток stdout, который имеет номер 1. Чтобы направить другой поток, надо перед оператором > поставить его номер.
Мы можем направлять одни потоки в направлении других:
В этом примере мы направили поток stdout в файл 1.txt, а затем направили stderr туда же, куда направлен stdout с помощью оператора & перед номером потока.
Теперь давайте поиграем с потоком stdin. Например, я хочу найти все папки «.svn» в некотором проекте и удалить:
Команда find с параметром. выводит в stdout все вложенные папки и файлы, которые находит в данной папке и во всех вложенных.
Теперь нам надо выбрать только папки с именем «.svn»:
Оператор | перенаправляет stdout одного приложения в stdin следующего. То есть все строки найденные с помощью find пошли в команду grep, которая выбирает строки по определенным условиям и выводит их. Здесь условие — это регулярное выражение, которое говорит о том, что строка должна заканчиваться на «/.svn».
Нужные папки мы выбрали, осталось их удалить.
И снова новый оператор: `. Он забирает stdout из команды, которую он окружает и вставляет в данное место как строку.
Получается, что мы запросили все файлы, выбрали из них папки с именем «.svn» и отдали результат как аргументы команде rm. В этом случае у нас будут проблемы если имена файлов и папок содержат пробелы. Исправляем ситуацию:
Что такое stdin, stdout и stderr в Linux?
Потоки объединяются в две точки
Потоки данных, как и водные потоки, имеют два конца. У них есть источник и отток. Какая бы команда Linux ни использовалась, она обеспечивает один конец каждого потока. Другой конец определяется оболочкой, запустившей команду. Этот конец будет подключен к окну терминала, подключен к каналу или перенаправлен к файлу или другой команде в соответствии с командной строкой, запустившей команду.
Стандартные потоки Linux
Потоки обрабатываются как файлы
Потоки в Linux, как и почти все остальное, рассматриваются как файлы. Вы можете читать текст из файла и записывать текст в файл. Оба эти действия включают поток данных. Так что концепция обработки потока данных в виде файла не так уж и сложна.
Каждому файлу, связанному с процессом, присваивается уникальный номер для его идентификации. Это называется файловым дескриптором. Всякий раз, когда требуется выполнить действие над файлом, дескриптор файла используется для идентификации файла.
Реакция на каналы и перенаправления
Мы можем очень легко увидеть это изменение в поведении. Попробуйте эти две команды:
Перенаправление stdout и stderr
Введите следующий текст в редактор и сохраните его в файл с именем error.sh.
Сделайте скрипт исполняемым с помощью этой команды:
Запустите сценарий с помощью этой команды:
Попробуем перенаправить вывод в файл:
Вывод из stdin был перенаправлен в файл, как и ожидалось.
Давайте еще раз попробуем провести наш тест, и на этот раз мы воспользуемся 2> :
Сообщение об ошибке перенаправляется, и сообщение stdout echo отправляется в окно терминала:
Посмотрим, что находится в файле capture.txt.
Сообщение stderr находится в файле capture.txt, как и ожидалось.
Перенаправление как stdout, так и stderr
Да мы можем. Эта команда направит stdout в файл с именем capture.txt и stderr в файл с именем error.txt.
Давайте проверим содержимое каждого файла:
Перенаправление stdout и stderr в один и тот же файл
Мы можем добиться этого с помощью следующей команды:
Давайте разберемся с этим.
Нет видимого вывода. Это обнадеживает.
Давайте проверим файл capture.txt и посмотрим, что в нем.
Оба потока stdout и stderr были перенаправлены в один файл назначения.
Обнаружение перенаправления в сценарии
Мы обсудили, как команда может определить, перенаправляется ли какой-либо из потоков, и может соответствующим образом изменить свое поведение. Можем ли мы сделать это в наших собственных сценариях? Да мы можем. И это очень простой метод для понимания и применения.
Введите следующий текст в редактор и сохраните его как input.sh.
Используйте следующую команду, чтобы сделать его исполняемым:
Если stdin подключен к окну терминала, тест подтвердится. Если stdin подключен к файлу или каналу, тест завершится неудачно.
Мы можем использовать любой удобный текстовый файл для генерации ввода в скрипт. Здесь мы используем файл dummy.txt.
Сценарий распознает, что его ввод передается по конвейеру. Или, точнее, он еще раз распознает, что поток stdin не подключен к окну терминала.
Давайте запустим скрипт без каналов и перенаправлений.
Поток stdin подключен к окну терминала, и сценарий сообщает об этом соответствующим образом.
Чтобы проверить то же самое с выходным потоком, нам нужен новый скрипт. Введите следующее в редактор и сохраните как output.sh.
Используйте следующую команду, чтобы сделать его исполняемым:
Сценарий распознает, что его вывод не идет напрямую в окно терминала.
Мы также можем протестировать сценарий, перенаправив вывод в файл.
Нет вывода в окно терминала, мы молча возвращаемся в командную строку. Как и следовало ожидать.
Мы можем заглянуть внутрь файла capture.txt, чтобы увидеть, что было захвачено. Для этого используйте следующую команду.
Опять же, простой тест в нашем скрипте обнаруживает, что поток stdout не отправляется непосредственно в окно терминала.
Если мы запустим сценарий без каналов или перенаправлений, он должен обнаружить, что stdout доставляется непосредственно в окно терминала.
И это именно то, что мы видим.
Потоки сознания
Знание того, как определить, подключены ли ваши скрипты к окну терминала, каналу или перенаправляются, позволяет вам соответствующим образом корректировать их поведение.
Вывод журнала и диагностики может быть более или менее подробным, в зависимости от того, идет ли он на экран или в файл. Сообщения об ошибках можно записывать в файл, отличный от обычного вывода программы.
Как это обычно бывает, чем больше знаний, тем больше возможностей.