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

Перенаправление ввода-вывода — возможность командной оболочки ряда операционных систем перенаправлять стандартные потоки в определённое пользователем место, например, в файл. Характерна для Unix-подобных операционных систем, но в разной степени реализована и в операционных системах других семейств.

Перенаправление вывода

Возможно, вы уже знакомы с некоторыми видами перенаправления, например, таким как:

$ ls -l >

сохраняющим вывод команды ls в файле с именем

Однако перенаправление позволяет сделать гораздо больше, чем демонстрирует этот простой пример. В главе 3 вы узнаете больше о дескрипторах стандартных файлов, а сейчас вам нужно знать только то, что дескриптор файла 0 соответствует стандартному вводу программы, дескриптор файла 1 — стандартному выводу, а дескриптор файла 2 — стандартному потоку ошибок. Каждый из этих файлов можно перенаправлять независимо друг от друга. На самом деле можно перенаправлять и другие дескрипторы файлов, но, как правило, нет нужды перенаправлять любые другие дескрипторы, кроме стандартных: 0, 1 и 2.

В предыдущем примере стандартный вывод перенаправлен в файл с помощью оператора >. По умолчанию, если файл с заданным именем уже есть, он будет перезаписан. Если вы хотите изменить поведение по умолчанию, можно применить команду set -о noclobber (или set -С), которая устанавливает опцию noclobber, чтобы помешать перезаписи при перенаправлении. Отменить эту опцию можно с помощью команды set +о noclobber. Позже в этой главе будут приведены другие опции команды set.

Для дозаписи в конец файла используйте оператор >>. Например, команда

ps >>

добавит вывод команды ps в конец заданного файла.

Для перенаправления стандартного потока ошибок перед оператором > вставьте номер дескриптора файла, который хотите перенаправить. Поскольку у стандартного потока ошибок дескриптор файла 2, укажите оператор 2>. Часто бывает полезно скрывать стандартный поток ошибок, запрещая вывод его на экран.

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

Команда

$ kill -HUP 1234 >killout. txt 2>

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

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

$ kill -1 1234 > 2>&1

поместит свой вывод и стандартный поток ошибок в один и тот же файл. Обратите внимание на порядок следования операторов. Приведенный пример читается как «перенаправить стандартный вывод в файл , а затем перенаправить стандартный поток ошибок туда же, куда и стандартный вывод». Если вы нарушите порядок, перенаправление выполнится не так, как вы ожидаете.

Поскольку обнаружить результат выполнения команды kill можно с помощью кода завершения (который будет подробно обсуждаться далее в этой главе), часто вам не потребуется сохранять какой бы то ни было стандартный вывод или стандартный поток ошибок. Для того чтобы полностью отбросить любой вывод, вы можете использовать универсальную «мусорную корзину» Linux, /dev/null, следующим образом:

$ kill -l 1234 >/dev/null 2>&1

Перенаправление стандартного потока ошибок

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

Обычно, когда обычный пользователь запускает команду find по всей системе, она выводит в терминал и полезные данные и ошибки. При этом, последних обычно больше, чем первых, что усложняет нахождение в выводе команды того, что нужно. Решить эту проблему довольно просто: достаточно перенаправить стандартный поток ошибок в файл, используя команду 2> (напомним, 2 — это дескриптор стандартного потока ошибок). В результате на экран попадёт только то, что команда отправляет в стандартный вывод:

Читайте также:  В iOS 13.4 Beta 3 найдена функция восстановления для iPhone

$ find / -name wireless 2> Как быть, если нужно сохранить результаты работы команды в отдельный файл, не смешивая эти данные со сведениями об ошибках? Так как потоки можно перенаправлять независимо друг от друга, в конец нашей конструкции можно добавить команду перенаправления стандартного потока вывода в файл:

$ find / -name wireless 2> > Обратите внимание на то, что первая угловая скобка идёт с номером — 2> , а вторая без него. Это так из-за того, что стандартный вывод имеет дескриптор 1, и команда > подразумевает перенаправление стандартного вывода, если номер дескриптора не указан.

И, наконец, если нужно, чтобы всё, что выведет команда, попало в один файл, можно перенаправить оба потока в одно и то же место, воспользовавшись командой &> :

$ find / -name wireless &>

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

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

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

#! / Bin / Баш echo «О попытке получить доступ к файлу, который не существует» cat

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

chmod + x

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

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

./

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

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

./>

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

кошка

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

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

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

1>

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

2>

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

./ 2>

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

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

кошка

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

[] — набор символов

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

Вы можете сформировать «подстановочный» знак с квадратными скобками ([]) и символами, которые они содержат. Соответствующий символ в имени файла должен соответствовать хотя бы одному из символов в наборе символов подстановки.

В этом примере команда переводит: «любой файл с» .txt», имя файла , начиная с „badge_0,“и в котором следующий символ либо 2, 4 или 6.»

ls badge_0 [246] .txt

Вы можете использовать более одного набора скобок на шаблон имени файла:

ls badge_ [01] [789] .txt

Вы также можете включить диапазоны в набор символов. Следующая команда выбирает файлы с номерами от 21 до 25 и от 31 до 35 в имени файла.

ls badge_ [23] [1-5] .txt