Программные каналы и потоки, перенаправление

Ноябрь 1st, 2010 Рубрики: bash, Linux, основы Linux

Программные потоки и каналы интерпертатора bashДоброго времени, читатели моего блога!
В данной статье хочу систематизировать свои знания по основным принципам работы программных потоков и каналов в интерпретаторе и в общем в ОС Linux, а так же о возможностях перенаправления данных потоков.
В самом начале хочу отметить, что интерпретатор работает с тремя стандартными потоками:

  1. stdout это стандартный поток вывода, который обеспечивает вывод команды. Дескриптор потока равен 1.
  2. stderr это стандартный поток ошибок, который выводит ошибки команд. Его дескриптор равен 2.
  3. stdin это стандартный поток ввода, который обеспечивает ввод командам. Его дескриптор равен 0.

Теперь простыми словами опишем, что эти три пункта обозначают:

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

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

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

Очень хорошо данные потоки изображены на рисунке, взятом с http://rus-linux.net/:

схематичное отображение программных потоков Linux

На данном изображении: Stdin, показан зеленым, имеет дескриптор 0
Stdout, показан красным, имеет дескриптор 1
Stderr, показан синим, имеет дескриптор 2

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

Итак, перенаправление потоков выполняется следующим образом:

$ command n>file

В данной строке показано: выполнение команды command и перенаправление потока (где n = дескриптору потока) в файл file. При выполнении данного перенаправления, если конечный файл существует, он будет перезаписан. При этом, если n не указан, то предполагается стандартный вывод.

$ command n>>file

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

$ command < file

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

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

find / -name .name_file > /path/to/file 2>&1

При выполнении данной команды, происходит поиск файла от корня файловой системы с именем .name_file и перенаправление результатов поиска (stdout и stderr) в файл /path/to/file. Конструкция > /path/to/file 2>&1 перенаправляет стандартный вывод в /path/to/file и вывод ошибок в стандартный вывод.  При этом: написание 2>&1 перед > не будет работать, так как когда интерпретатор прочитает 2>&1, он еще не знает куда перенаправлен стандартный поток вывода, поэтому потоки ошибок и вывода не будут объединены.

$ command > file 2>&1

аналогична написанию:

$ command &> file

или:

$ command 2>&file

Если необходимо проигнорировать вывод, его можно направить в устройство /dev/null, это своего рода "черная дыра", принимающая любое количество информации и превращающая ее в ничто.

Думаю приведенной информации о перенаправлении потоко будет достаточно для понимания сути, теперь расскажу о конвеерной передаче.

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

$ command1 | command2

В данном примере выполняется команда command1, ее поток вывода используется,  как поток ввода при выполнении command2 .

На сегодня все. Буду рад комментариям и дополнениям. Спасибо.

С Уважением, Mc.Sim!




Теги: , , ,

5 комментариев к “Программные каналы и потоки, перенаправление”

  1. Kirill K
    Январь 21st, 2013 at 14:24
    1

    find / -name .name_file > /path/to/file 2>&1
    мне не понятно т.е получается что результат поиска отправиться в file, а результаты выполненые с ошибок отправиться тоже туда?

    • Январь 28th, 2013 at 22:07
      2

      Не совсем так.
      т.е получается что результат поиска отправиться в file, а результаты выполненые с ошибок отправиться тоже туда? поток ошибок (stderr) отправляется в поток сообщений (stdout).
      Т.к. bash читает команды слева направо, то он сначала прочитает, что stdout нужно отправить в file, а затем прочитает, что stderr нужно направить в stdout. Если задать сначала 2>&1, а потом > /path/to/file, то при чтении команды bash направит stderr на консоль, т.к. не будет знать куда отправлен stdout во время прочтения 2>&1.
      Надеюсь, что понятно объяснил )

  2. Kirill K
    Январь 30th, 2013 at 14:18
    3

    почти =) , получается из примера он отправит ошибки на консоль?

    • Февраль 4th, 2013 at 00:23
      4

      Не, если команду задать как
      find / -name .name_file 2>&1 > /path/to/file
      то ошибки будут выводиться на консоль.

Написать комментарий