Оператор перенаправления вывода linux

Перенаправление стандартных потоков данных в Linux

Введение

Наблюдая за заводом извне, мы замечаем три потока:

    0. На территорию завода поступает входящий поток «сырья» — данных подлежащих переработке.

1. Из ворот выходит поток продукции — данных, подвергшихся переработке на заводе-процессе.

  • 2. Из трубы поднимается дым, по виду которого можно судить о работе завода. Если дыма не заметно, то завод работает нормально (у нас ведь экологически чистое производство информации). Если вдруг повалил густой дым, то, ясное дело, что-то не в порядке.
  • На компьютерном языке эти три потока данных называются стандартными потоками. Каждый имеет числовой дескриптор (номер), название и направление по умолчанию.

    Дескриптор 0: Входящий стандартный поток (Standart Input, stdin). По умолчанию, поступает со стандартного устройства ввода (обычно с клавиатуры).

    Дескриптор 1: Выходящий стандартный поток (Standar Output, stdout). По умолчанию направляется на стандартное устройство вывода (обычно экран монитора).

    Дескриптор 2: Стандартный поток сообщений об ошибках (Standart Error, stderr). С английского переводится как «стандартная ошибка», но в русском языке такое выражение звучит двусмысленно. Поэтому я предпочитаю называть его стандартным сообщением, тем более, что в большинстве случаев оно сообщает не об ошибке, а о ходе процесса. По умолчанию направляется туда же, куда и стандартный вывод — на экран монитора, но не смешивается со стандартным выводом, а раскладывается по разным «полкам».

    Входящий поток, показан зеленым, имеет дескриптор 0
    Выходящий поток, показан красным, имеет дескриптор 1
    Поток сообщений, показан синим, имеет дескриптор 2

    Вот пример стандартного ввода и вывода:

    Команда echo направляет поток данных с клавиатуры на экран дисплея.

    А вот пример стандартного сообщения об ошибке:

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

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

    Как видите, на экране не появились слова «стандартный ввод», зато в текущей директории появился файл ввод.txt с этими словами.

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

    Проделайте этот опыт самостоятельно, чтобы убедиться, что это так. Для определения текущей директории применяется команда pwd:

    Это я на случай, если вы не сразу найдете файл ввод.txt. (pwd расшифровывается как «print working directory» — «сообщить рабочую директорию»).

    Внимание: Следите за тем, в какой директории вы находитесь и без надобности не перенаправляйте вывод в существующие файлы. Могут быть уничтожены важные файлы (особенно, если вы имеете дурную привычку работать под логином администратора — root’а).

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

    Например, команда tr, которая служит для перевода (замены) выбранных символов в другие символы или удаления их.

    На этот случай служит оператор перенаправления ввода ), предварив его номером перенаправляемого потока. Стандартный поток сообщений имеет дескриптор (номер) 2, вот и поставим двойку перед оператором перенаправления — 2> . Куда же перенаправить этот поток? Можно перенаправить в какой-нибудь файл, если хотите на досуге разобраться с этими сообщениями. (Например, при компиляции программ выдается множество сообщений, которые вовсе не бессмысленны). А если сообщения вам не нужны, то лучше перенаправить их в файл /dev/null. Это специальный файл, который принимает любое количество данных и обращает их в ничто — эдакая бездонная и безвозвратная мусорная корзина, а лучше — «черная дыра». Вот в нее то и направим ненужный поток сообщений:

    В итоге получаем на экране только вывод программы.

    Возникает резонный вопрос: «А можно ли прочитать на экране только сообщения, а вывод программы перенаправить в файл?». Конечно можно:

    а, принимая во внимание, что перенаправляется по умолчанию только стандартный вывод (поток номер 1), то единичку перед оператором перенаправления ставить ни к чему, результат будет один:

    Читайте также:  Linux изменить доступ ко всем файлам

    Существует также возможность перенаправить потоки 1 и 2 в разные файлы:

    Убедитесь сами, что файл wc.txt не содержит стандартных сообщений.

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

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

    Источник

    Bash-скрипты, часть 4: ввод и вывод

    В прошлый раз, в третьей части этой серии материалов по bash-скриптам, мы говорили о параметрах командной строки и ключах. Наша сегодняшняя тема — ввод, вывод, и всё, что с этим связано.

    Вы уже знакомы с двумя методами работы с тем, что выводят сценарии командной строки:

    • Отображение выводимых данных на экране.
    • Перенаправление вывода в файл.

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

    Стандартные дескрипторы файлов

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

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

    • 0 , STDIN — стандартный поток ввода.
    • 1 , STDOUT — стандартный поток вывода.
    • 2 , STDERR — стандартный поток ошибок.

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

    STDIN

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

    Многие команды bash принимают ввод из STDIN , если в командной строке не указан файл, из которого надо брать данные. Например, это справедливо для команды cat .

    Когда вы вводите команду cat в командной строке, не задавая параметров, она принимает ввод из STDIN . После того, как вы вводите очередную строку, cat просто выводит её на экран.

    STDOUT

    STDOUT — стандартный поток вывода оболочки. По умолчанию это — экран. Большинство bash-команд выводят данные в STDOUT , что приводит к их появлению в консоли. Данные можно перенаправить в файл, присоединяя их к его содержимому, для этого служит команда >> .

    Итак, у нас есть некий файл с данными, к которому мы можем добавить другие данные с помощью этой команды:

    То, что выведет pwd , будет добавлено к файлу myfile , при этом уже имеющиеся в нём данные никуда не денутся.

    Перенаправление вывода команды в файл

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

    После выполнения этой команды мы увидим сообщения об ошибках на экране.

    Попытка обращения к несуществующему файлу

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

    STDERR

    STDERR представляет собой стандартный поток ошибок оболочки. По умолчанию этот дескриптор указывает на то же самое, на что указывает STDOUT , именно поэтому при возникновении ошибки мы видим сообщение на экране.

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

    ▍Перенаправление потока ошибок

    Как вы уже знаете, дескриптор файла STDERR — 2. Мы можем перенаправить ошибки, разместив этот дескриптор перед командой перенаправления:

    Читайте также:  Как узнать gpt или mbr диск linux

    Сообщение об ошибке теперь попадёт в файл myfile .

    Перенаправление сообщения об ошибке в файл

    ▍Перенаправление потоков ошибок и вывода

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

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

    Оболочка перенаправит то, что команда ls обычно отправляет в STDOUT , в файл correctcontent благодаря конструкции 1> . Сообщения об ошибках, которые попали бы в STDERR , оказываются в файле errorcontent из-за команды перенаправления 2> .

    Если надо, и STDERR , и STDOUT можно перенаправить в один и тот же файл, воспользовавшись командой &> :

    Перенаправление STDERR и STDOUT в один и тот же файл

    После выполнения команды то, что предназначено для STDERR и STDOUT , оказывается в файле content .

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

    Существует два метода перенаправления вывода в сценариях командной строки:

    • Временное перенаправление, или перенаправление вывода одной строки.
    • Постоянное перенаправление, или перенаправление всего вывода в скрипте либо в какой-то его части.

    ▍Временное перенаправление вывода

    В скрипте можно перенаправить вывод отдельной строки в STDERR . Для того, чтобы это сделать, достаточно использовать команду перенаправления, указав дескриптор STDERR , при этом перед номером дескриптора надо поставить символ амперсанда ( & ):

    Если запустить скрипт, обе строки попадут на экран, так как, как вы уже знаете, по умолчанию ошибки выводятся туда же, куда и обычные данные.

    Запустим скрипт так, чтобы вывод STDERR попадал в файл.

    Как видно, теперь обычный вывод делается в консоль, а сообщения об ошибках попадают в файл.

    Сообщения об ошибках записываются в файл

    ▍Постоянное перенаправление вывода

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

    Перенаправление всего вывода в файл

    Если просмотреть файл, указанный в команде перенаправления вывода, окажется, что всё, что выводилось командами echo , попало в этот файл.

    Команду exec можно использовать не только в начале скрипта, но и в других местах:

    Вот что получится после запуска скрипта и просмотра файлов, в которые мы перенаправляли вывод.

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

    Сначала команда exec задаёт перенаправление вывода из STDERR в файл myerror . Затем вывод нескольких команд echo отправляется в STDOUT и выводится на экран. После этого команда exec задаёт отправку того, что попадает в STDOUT , в файл myfile , и, наконец, мы пользуемся командой перенаправления в STDERR в команде echo , что приводит к записи соответствующей строки в файл myerror.

    Освоив это, вы сможете перенаправлять вывод туда, куда нужно. Теперь поговорим о перенаправлении ввода.

    Перенаправление ввода в скриптах

    Для перенаправления ввода можно воспользоваться той же методикой, которую мы применяли для перенаправления вывода. Например, команда exec позволяет сделать источником данных для STDIN какой-нибудь файл:

    Эта команда указывает оболочке на то, что источником вводимых данных должен стать файл myfile , а не обычный STDIN . Посмотрим на перенаправление ввода в действии:

    Вот что появится на экране после запуска скрипта.

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

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

    Создание собственного перенаправления вывода

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

    Назначить дескриптор для вывода данных можно, используя команду exec :

    Читайте также:  Диск размечен под линукс

    После запуска скрипта часть вывода попадёт на экран, часть — в файл с дескриптором 3 .

    Перенаправление вывода, используя собственный дескриптор

    Создание дескрипторов файлов для ввода данных

    Перенаправить ввод в скрипте можно точно так же, как и вывод. Сохраните STDIN в другом дескрипторе, прежде чем перенаправлять ввод данных.

    После окончания чтения файла можно восстановить STDIN и пользоваться им как обычно:

    В этом примере дескриптор файла 6 использовался для хранения ссылки на STDIN . Затем было сделано перенаправление ввода, источником данных для STDIN стал файл. После этого входные данные для команды read поступали из перенаправленного STDIN , то есть из файла.

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

    Закрытие дескрипторов файлов

    Оболочка автоматически закрывает дескрипторы файлов после завершения работы скрипта. Однако, в некоторых случаях нужно закрывать дескрипторы вручную, до того, как скрипт закончит работу. Для того, чтобы закрыть дескриптор, его нужно перенаправить в &- . Выглядит это так:

    После исполнения скрипта мы получим сообщение об ошибке.

    Попытка обращения к закрытому дескриптору файла

    Всё дело в том, что мы попытались обратиться к несуществующему дескриптору.

    Будьте внимательны, закрывая дескрипторы файлов в сценариях. Если вы отправляли данные в файл, потом закрыли дескриптор, потом — открыли снова, оболочка заменит существующий файл новым. То есть всё то, что было записано в этот файл ранее, будет утеряно.

    Получение сведений об открытых дескрипторах

    Для того, чтобы получить список всех открытых в Linux дескрипторов, можно воспользоваться командой lsof . Во многих дистрибутивах, вроде Fedora, утилита lsof находится в /usr/sbin . Эта команда весьма полезна, так как она выводит сведения о каждом дескрипторе, открытом в системе. Сюда входит и то, что открыли процессы, выполняемые в фоне, и то, что открыто пользователями, вошедшими в систему.

    У этой команды есть множество ключей, рассмотрим самые важные.

    • -p Позволяет указать ID процесса.
    • -d Позволяет указать номер дескриптора, о котором надо получить сведения.

    Для того, чтобы узнать PID текущего процесса, можно использовать специальную переменную окружения $$ , в которую оболочка записывает текущий PID .

    Ключ -a используется для выполнения операции логического И над результатами, возвращёнными благодаря использованию двух других ключей:

    Вывод сведений об открытых дескрипторах

    Тип файлов, связанных с STDIN , STDOUT и STDERR — CHR (character mode, символьный режим). Так как все они указывают на терминал, имя файла соответствует имени устройства, назначенного терминалу. Все три стандартных файла доступны и для чтения, и для записи.

    Посмотрим на вызов команды lsof из скрипта, в котором открыты, в дополнение к стандартным, другие дескрипторы:

    Вот что получится, если этот скрипт запустить.

    Просмотр дескрипторов файлов, открытых скриптом

    Скрипт открыл два дескриптора для вывода ( 3 и 6 ) и один — для ввода ( 7 ). Тут же показаны и пути к файлам, использованных для настройки дескрипторов.

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

    Иногда надо сделать так, чтобы команды в скрипте, который, например, может исполняться как фоновый процесс, ничего не выводили на экран. Для этого можно перенаправить вывод в /dev/null . Это — что-то вроде «чёрной дыры».

    Вот, например, как подавить вывод сообщений об ошибках:

    Тот же подход используется, если, например, надо очистить файл, не удаляя его:

    Итоги

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

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

    Уважаемые читатели! В этом материале даны основы работы с потоками ввода, вывода и ошибок. Уверены, среди вас есть профессионалы, которые могут рассказать обо всём этом то, что приходит лишь с опытом. Если так — передаём слово вам.

    Источник

    Оцените статью