Потоки вывода в Unix (bash/sh)
Сообщения от скриптов и программ выводятся в определенные потоки вывода.
Т.е. написав в терминале echo "I am your PC", результат выводится на экран, но с точки зрения компьютера результат выводится через определенный поток вывода в терминал. В случае echo это поток под номером 1, называется stdout (с ним ассоциирован экран).
Некоторые программы еще используют другой поток вывода с номером 2, который называется stderr. В него они выводятся сообщения об ошибках.
Перенаправим все обычные информационные сообщения команды ls в файл test.file:
$ ls > test.file |
Получим таким образом в этом файле ответ команды ls.
При этом мы не увидим ничего на экране, а в файле test.file будет находится все то, что должно было отобразиться на экране.
Теперь сделаем ошибочную команду:
$ ls /hren > test.file |
Т.к. директории «hren» в корне файловой системы нет, то команда ls выдаст ошибку. Однако вывалит ее не через обычный поток stdout, а через поток ошибок stderr. А перенаправление задано лишь для stdout.
Теперь выполним команду ls так, чтобы данные записались в файл test.file, а сообщения об ошибках в файл test.stderror, при этом на экране во время выполнения не появится ничего:
$ ls >test.file 2>test.stderror |
Запись "2>test.stderror" указывает, что поток с номером 2 (stderr) нужно перенаправить в файл test.stderror.
Иногда встречается запись 2>&1. Она означает, что поток с номером 2 перенаправить в поток с номером 1, т.е. поток stderr - направить через поток stdout.
$ ls /hren 2>&1 |
Перенаправим все сообщения в файл test.file:
$ ls /hren >test.file 2>&1 |
При этом все сообщения, как об ошибках, так и обычные, будут записаны в test.file, т.к. поток stdout мы сначала перенаправили в файл, а потом указали, что ошибки нужно отправить в stdout,т.е. в файл test.file
Иногда появляется необходимость скрыть все выдаваемые сообщения. Для этого можно использовать устройство /dev/null.
Весь вывод обычных сообщений команды ls мы направим в /dev/null:
$ ls > /dev/null |
На экране не увидим ничего, кроме сообщений об ошибках.
В этом примере также сообщения об ошибках будут отправлены в девнулл:
$ ls > /dev/null 2>&1 |
Причем эта запись тоже что и эта:
$ ls >/dev/null 2>/dev/null |
А в этом примере уберем только сообщения об ошибках:
$ ls 2>/dev/null |
Кстати, здесь уже нельзя указывать "2>&1", т.к. поток stdout не перенаправлен никуда и в таком случае сообщения об ошибках будут выданы на экран.
Еще два примера. Порядок указателей перенаправления играет роль!
Интерпретаторы читают и применяют перенаправления слева направо.
1)
$ ls >/dev/null 2>&1 |
">/dev/null" - мы направляем поток 1 (stdout) в /dev/null.
"2>&1" - мы перенаправляем поток 2 (stderr) в поток 1 (stdout). Но, т.к. поток 1 уже ассоциирован с /dev/null все сообщения все-равно попадут в /dev/null.
В результате на экране пусто.
2)
$ ls 2>&1 >/dev/null |
"2>&1" - мы перенаправляем поток ошибок stderr (2) в поток stdout (1). Но, т.к. поток 1 по-умолчанию ассоциирован с терминалом - сообщения об ошибках мы успешно увидим на экране.
">/dev/null" - а уже здесь мы перенаправляем поток 1 в /dev/null. И обычные сообщения мы не увидим.
В результате мы будем видеть сообщения об ошибках на экране, но не будем видеть обычные сообщения.
Обновлено 06.04.2016 07:23