Программные каналы и потоки, перенаправление
Доброго времени, читатели моего блога!
В данной статье хочу систематизировать свои знания по основным принципам работы программных потоков и каналов в интерпретаторе и в общем в ОС Linux, а так же о возможностях перенаправления данных потоков.
В самом начале хочу отметить, что интерпретатор работает с тремя стандартными потоками:
- stdout это стандартный поток вывода, который обеспечивает вывод команды. Дескриптор потока равен 1.
- stderr это стандартный поток ошибок, который выводит ошибки команд. Его дескриптор равен 2.
- stdin это стандартный поток ввода, который обеспечивает ввод командам. Его дескриптор равен 0.
Теперь простыми словами опишем, что эти три пункта обозначают:
stdout – стандартный поток вывода. Это, говоря простым языком, та информация, которую мы видим в интерпретаторе при выполнении команд. То есть все сообщения (без сообщений об ошибках), которые выполняемая в интерпретаторе команда сообщает и выводит на терминал (читай – экран). (вывод на экран задан по умолчанию, но можно указать и вывод, например в файл или перенаправление в другую команду, как это делается, расскажу ниже)
stderr – поток ошибок. Это ошибки при выполнении команд в bash, которые по умолчанию выводятся на stdout, то есть на терминал (опять же, если не указан вывод в другое место)
stdin – поток ввода. Это, говоря простым языком – то, что мы вводим с клавиатуры в интерпретатор для выполнения команды.
Очень хорошо данные потоки изображены на рисунке, взятом с http://rus-linux.net/:
На данном изображении: 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!
find / -name .name_file > /path/to/file 2>&1
мне не понятно т.е получается что результат поиска отправиться в file, а результаты выполненые с ошибок отправиться тоже туда?
Не совсем так.
т.е получается что результат поиска отправиться в file, а
результаты выполненые с ошибок отправиться тоже туда?поток ошибок (stderr) отправляется в поток сообщений (stdout).Т.к. bash читает команды слева направо, то он сначала прочитает, что stdout нужно отправить в file, а затем прочитает, что stderr нужно направить в stdout. Если задать сначала 2>&1, а потом > /path/to/file, то при чтении команды bash направит stderr на консоль, т.к. не будет знать куда отправлен stdout во время прочтения 2>&1.
Надеюсь, что понятно объяснил )
почти
, получается из примера он отправит ошибки на консоль?
Не, если команду задать как
find / -name .name_file 2>&1 > /path/to/file
то ошибки будут выводиться на консоль.