Библиотека сайта rus-linux.net
Перенаправление стандартных потоков данных в Linux
Алексей Дмитриев, февраль 2009.Введение
Прежде чем заводить речь о перенаправлениях, нужно представлять себе работу процесса в Юниксовидных ОС. Вдаваться во внутреннюю структуру процесса не входит в наши намерения, мы будем рассматривать процесс как некий "черный ящик", а лучше завод, перерабатывающий данные.Наблюдая за заводом извне, мы замечаем три потока:
- 0. На территорию завода поступает входящий поток "сырья" - данных подлежащих переработке.
- 1. Из ворот выходит поток продукции - данных, подвергшихся переработке на заводе-процессе.
- 2. Из трубы поднимается дым, по виду которого можно судить о работе завода. Если дыма не заметно, то завод работает нормально (у нас ведь экологически чистое производство информации). Если вдруг повалил густой дым, то, ясное дело, что-то не в порядке.
На компьютерном языке эти три потока данных называются стандартными потоками. Каждый имеет числовой дескриптор (номер), название и направление по умолчанию.
Дескриптор 0: Входящий стандартный поток (Standart Input, stdin). По умолчанию, поступает со стандартного устройства ввода (обычно с клавиатуры).
Дескриптор 1: Выходящий стандартный поток (Standar Output, stdout). По умолчанию направляется на стандартное устройство вывода (обычно экран монитора).
Дескриптор 2: Стандартный поток сообщений об ошибках (Standart Error, stderr). С английского переводится как "стандартная ошибка", но в русском языке такое выражение звучит двусмысленно. Поэтому я предпочитаю называть его стандартным сообщением, тем более, что в большинстве случаев оно сообщает не об ошибке, а о ходе процесса. По умолчанию направляется туда же, куда и стандартный вывод - на экран монитора, но не смешивается со стандартным выводом, а раскладывается по разным "полкам".
Выходящий поток, показан красным, имеет дескриптор 1
Поток сообщений, показан синим, имеет дескриптор 2
Вот пример стандартного ввода и вывода:
$ echo стандарный ввод (Enter) стандарный ввод
Команда echo направляет поток данных с клавиатуры на экран дисплея.
А вот пример стандартного сообщения об ошибке:
$ cat file.txt cat: file.txt: Нет такого файла или каталога
Каждый из этих стандартных потоков можно перенаправлять, то есть направлять не туда, куда поток направляется по умолчанию. Это и есть перенаправление.
Перенаправление стандартного вывода
Во многих случаях удобнее работать не со стандартным выводом на монитор, а с файлами. Файлы можно сохранять, редактировать, посылать по почте, и т.д. Мы всегда можем перенаправить вывод команды в файл, применив оператор перенаправления > и указав имя файла. При этом не важно, существует ли такой файл на самом деле. Если такого файла нет, то он будет создан, а если есть, то перезаписан (все прежнее содержимое будет стерто, а новое записано).
$ echo стандарный ввод > ввод.txt
Как видите, на экране не появились слова "стандартный ввод", зато в текущей директории появился файл ввод.txt с этими словами.
Можно дописать в файл ввод.txt вывод других команд, не уничтожая имеющегося содержимого. Для этого служит оператор >>
$ echo и стандарный вывод >> ввод.txt
Проделайте этот опыт самостоятельно, чтобы убедиться, что это так. Для определения текущей директории применяется команда pwd:
$ pwd /home/ваш_логин/
Это я на случай, если вы не сразу найдете файл ввод.txt. (pwd расшифровывается как "print working directory" - "сообщить рабочую директорию").
Внимание: Следите за тем, в какой директории вы находитесь и без надобности не перенаправляйте вывод в существующие файлы. Могут быть уничтожены важные файлы (особенно, если вы имеете дурную привычку работать под логином администратора - root'а).
Перенаправление ввода
Не все команды принимают файлы в качестве аргумента; некоторые принимают данные только из стандартного ввода.Например, команда tr, которая служит для перевода (замены) выбранных символов в другие символы или удаления их.
На этот случай служит оператор перенаправления ввода < .
$ tr [a-z] [A-Z] < case.txt TRANSLATION LOWER CASE INTO UPPERCASE
В файле case.txt содержался тот же текст, только написанный строчными буквами.
Если желательно записать результат работы команды в другой файл, то можно совместить перенаправление ввода с перенаправлением вывода:
$ tr [a-z] [A-Z] < case.txt > case-upper.txt
Появится файл case-upper.txt, содержащий только что виденный нами текст.
И, наконец, можно дописать изменения текста в исходный файл:
$ tr [a-z] [A-Z] < case.txt >> case.txt
А вот пытаться переписать исходный файл измененным текстом не получится - будут утеряны и исходный файл и результат изменений:
$ tr [a-z] [A-Z] < case.txt > case.txt
Попробуйте сами...
Перенаправление стандартного потока сообщений
Если команда "страдает болтливостью", то есть выводит множество сообщений, которые вам не нужны, или непонятны, то лучше перенаправить поток этих сообщений в другое русло. Вывод ненужных сообщений замедляет работу команды, засоряет экран монитора, отвлекает от работы.Например, команда wc, которая подсчитывает количество строк, слов, байт, или символов, работает только с текстовыми файлами (кроме опции -с). Если среди заданных команде для обработки файлов попадутся бинарные или .html файлы, то команда выдаст множество сообщений. Зададим команде wc просчитать все файлы в текущей директории (при помощи символа астериска - *)
$ wc * wc: Documents: Is a directory 0 0 0 Documents 9 14 207 MyComputer.desktop 310 1963 12555 bookindx.txt 2 5 39 case-upper.txt 2 5 38 case.txt wc: mill.gif:1: Invalid or incomplete multibyte or wide character wc: mill.gif:2: Invalid or incomplete multibyte or wide character wc: mill.gif:3: Invalid or incomplete multibyte or wide character wc: mill.gif:4: Invalid or incomplete multibyte or wide character wc: mill.gif:5: Invalid or incomplete multibyte or wide character wc: mill.gif:6: Invalid or incomplete multibyte or wide character 73 307 12702 mill.gif 119 745 9468 redirections_and_pipes.txt wc: sed.html:53: Invalid or incomplete multibyte or wide character 2732 14592 167105 sed.html 682 4198 29314 sed_mcmahon.txt 114 156 1715 shema.txt 150 318 5066 trash.desktop 15 18 258 Дисковод 1 0 2 Текстовый файл 4209 22321 238469 итого
Строки вывода, начинающиеся с wc: являются сообщениями. На самом деле этих сообщений было намного больше, мне пришлось уменьшить их количество, чтобы не загромождать статью.
Избавиться от них очень просто: нужно воспользоваться тем же оператором перенаправления (>), предварив его номером перенаправляемого потока. Стандартный поток сообщений имеет дескриптор (номер) 2, вот и поставим двойку перед оператором перенаправления - 2> . Куда же перенаправить этот поток? Можно перенаправить в какой-нибудь файл, если хотите на досуге разобраться с этими сообщениями. (Например, при компиляции программ выдается множество сообщений, которые вовсе не бессмысленны). А если сообщения вам не нужны, то лучше перенаправить их в файл /dev/null. Это специальный файл, который принимает любое количество данных и обращает их в ничто - эдакая бездонная и безвозвратная мусорная корзина, а лучше - "черная дыра". Вот в нее то и направим ненужный поток сообщений:
$ wc * 2> /dev/null 0 0 0 Documents 9 14 207 MyComputer.desktop 310 1963 12555 bookindx.txt 2 5 39 case-upper.txt 2 5 38 case.txt 73 307 12702 mill.gif 119 745 9468 redirections_and_pipes.txt 2732 14592 167105 sed.html 682 4198 29314 sed_mcmahon.txt 114 156 1715 shema.txt 150 318 5066 trash.desktop 15 18 258 Дисковод 1 0 2 Текстовый файл 4209 22321 238469 итого
В итоге получаем на экране только вывод программы.
Возникает резонный вопрос: "А можно ли прочитать на экране только сообщения, а вывод программы перенаправить в файл?". Конечно можно:
$ wc * 1> /dev/null
а, принимая во внимание, что перенаправляется по умолчанию только стандартный вывод (поток номер 1), то единичку перед оператором перенаправления ставить ни к чему, результат будет один:
$ wc * > /dev/null wc: Documents: Is a directory wc: mill.gif:1: Invalid or incomplete multibyte or wide character wc: mill.gif:2: Invalid or incomplete multibyte or wide character wc: mill.gif:3: Invalid or incomplete multibyte or wide character ...
Существует также возможность перенаправить потоки 1 и 2 в разные файлы:
$ wc * > wc.txt 2> /dev/null
Убедитесь сами, что файл wc.txt не содержит стандартных сообщений.
И последняя хитрость. Можно направить оба выходных потока: стандарный вывод и стандартное сообщение в один и тот же файл, так, чтобы в файле сохранить все, что мы увидели бы на экране монитора:
$ wc * > wc.txt 2>&1
Первый оператор перенаправления направляет стандартный вывод в файл, а второй оператор перенаправления указывает, что стандартное сообщение следует направить туда же, куда и поток номер 1.