Стандартные потоки вывода (stdout) Windows
07.02.2018
Категория: Разное
С помощью переназначения устройств ввода/вывода одна программа может направить свой вывод на вход другой или перехватить вывод другой программы, используя его в качестве своих входных данных. Таким образом, имеется возможность передавать информацию от процесса к процессу при минимальных программных издержках.
Есть 3 файловых дескриптора: stdin
— стандартный ввод, stdout
— стандартный вывод и stderr
— стандартный поток ошибок. В скриптах 1 означает stdout
, а 2 — stderr
.
Практически это означает, что для программ, которые используют стандартные входные и выходные устройства, операционная система позволяет:
- перенаправлять
stdout
в файл - перенаправлять
stderr
в файл - перенаправлять
stdout
вstderr
- перенаправлять
stderr
вstdout
- перенаправлять
stderr
иstdout
в файл - перенаправлять
stderr
иstdout
вstdout
- перенаправлять
stderr
иstdout
вstderr
- перенаправление
stderr
иstdout
по конвейеру
Все вышесказанное является привычной обыденностью для любого пользователя любой nix системы, но в среде Windows, данные возможности применяются крайне редко, хотя на самом деле они там есть и всё практически идентично.
А теперь примеры:1. Перенаправление стандартного потока программы в файл с заменой содержимого файла
ping ya.ru -t > log.txt
ping ya.ru -t 1> log.txt
при этом на экран ничего кроме ошибок не выводится, а все записывается в лог. Если остановить пинг, и запустить заново, предыдущий лог полностью затирается новым.
2. Перенаправление стандартного потока программы в файл с до записью содержимого лога
ping ya.ru -t >> log.txt
Тоже самое, но при прерывание пинга и начале нового, старое содержимое лога не затрется, а новое дописывается в конец
ping ya.ru -t 1>> log.txt
3. Перенаправление потока ошибок программы в фаил с заменой содержимого
ping ya.ru -t 2> log.txt
при этом, стандартный поток программы пойдет на экран, а ошибки будут записаны в лог, с заменой содержимого.
4. То же самое, но с до записью содержимого лога.
ping ya.ru -t 2>> log.txt
5. Следующая конструкция позволяет перенаправить информацию между потоками (между стандартным потоком и потоком ошибок, или наоборот).
ping ya.ru > log.txt 2>&1
или с до записью лога
ping ya.ru >> log.txt 2>&1
В данном примере стандартный поток ошибок пересылается в стандартный поток (конструкция 2>&1
) а потом стандартный поток (уже с завернутым в него потоком ошибок) посылается в лог.
6. В этом примере все наоборот, стандартный поток, пересылается в поток ошибок и уже поток ошибок перенаправляется в лог:
ping ya.ru > log.txt 1>&2
или с до записью лога
ping ya.ru >> log.txt 1>&2
7. По аналогии с Linux системами в Windows можно перенаправить весь или часть вывода программы в виртуальное устройство, а проще говоря слить в мусор.
Таким устройством является nul, и делать перенаправление в него можно используя все выше представленные комбинации. Например
ping ya.ru > nul
В Linux есть еще одна конструкция перенаправления, а именно &>/var/log/log.txt
, она перенаправляет ВСЕ без исключения потоки программы в указанное место, по сути являясь более коротким и более грамотным аналогом конструкции >log.txt 1>&2
. Но к сожалению в Windows это не работает.
А теперь давайте немного разберемся в прикладных различиях между работой данных методов. В нормальных приложениях все разбито на потоки, но у большинства виндовых утилит это не так, пинг например, пишет все в стандартный поток (на экран), поэтому для него конструкция вида 2>
не имеет смысла. Но есть еще не виндовые утилиты, для примера возьмем curl
(мой любимый).
Он разделяет 3 вида вывода, вывод полезной информации, вывод служебной информации и вывод ошибок. Если перенаправить вывод так: >
или >>
или 1>
или 1>>
то по завершению запроса отобразится служебная информация о запросе, а вся полезная информация уйдет в лог (это именно то, что уходит по конвейеру |
).
А теперь сделаем заведомо ошибочный запрос, изменив протокол http
на http3
не меняя вывода в лог. В итоге мы получим ошибку на экране.
Изменим вывод в лог на один из этих: 2>
или 2>>
ошибка ранее выводившаяся на экран, попала в лог, и на экране ничего не будет (служебной информации нет, так как запрос произведен не был).
Вернемся к первому скриншоту на котором мы видим вывод служебной информации, по сути, не будь у курла ключа -s
который подавляет вывод служебной информации, нам пришлось бы пользоваться конструкциями из пятого и шестого примеров.
И вывод был бы таким:
То есть, полная тишина, вся информация, как то полезный вывод, ошибки программы, служебная информация, все ушло в лог.
На данном скриншоте, конструкцией 2>&1
мы завернули поток ошибок в стандартный поток, а конструкцией > 5555.txt
стандартный поток перенаправили в лог. Если вместо > 5555.txt
использовать 2> 5555.txt
, то есть перенаправить в лог стандартный поток ошибок, мы увидим весь вывод программы (и ошибки, и служебную информацию и полезный вывод) на экране. Конструкция 2>&1
имеет больший приоритет, а по ней уже все завернуто в стандартный поток.
Делать пример с заворотом стандартного потока в поток ошибок (1>&2
) я не буду, ибо там все точно так же.
Надеюсь логика понятна…
Так же с помощью символа<
можно прочитать входные данные для заданной команды не с клавиатуры, а из определенного (заранее подготовленного) файла. Для примера возьмем реальный и вполне полезный случай. Например, у нас есть файл log.txt и нам надо посчитать сколько в нем строк. Сделать это можно с помощью такой конструкции
find /c /v "" log.txt
но вывод будет не совсем приемлемым.
А вот если сделать так:
find /c /v "" < log.txt
то все будет именно так как надо.
Это происходит потому что в первом случае, файл обрабатывается как файл, а во втором, как поток (аналог линуксового конвейера cat log.txt |
) в общем, <
это виндовый аналог cat
со всеми вытекающими.