Что означает "2>&1"?
Я пытаюсь объединить потоки stderr и stdout в один поток stdout и применяю для этого следующий синтаксис к команде:
2>&1
Например, следующая команда позволяет мне увидеть несколько первых ошибок при компиляции файла main.cpp:
g++ main.cpp 2>&1 | head
Но что именно означает конструкция 2>&1?
5 ответ(ов)
Файловый дескриптор 1 — это стандартный вывод (stdout).
Файловый дескриптор 2 — это стандартная ошибка (stderr).
Сначала конструкция 2>1 может показаться хорошим способом перенаправить stderr в stdout. Однако на самом деле она будет интерпретироваться как "перенаправить stderr в файл с именем 1".
Символ & указывает, что то, что идет до и после, является файловым дескриптором, а не именем файла. Поэтому мы используем 2>&1. Рассматривайте >& как оператор слияния перенаправлений.
Чтобы перенаправить стандартный вывод (stdout) в файл file.txt, вы можете использовать следующую команду:
echo test > file.txt
Эта команда аналогична:
echo test 1> file.txt
Для перенаправления стандартного ошибок (stderr) в файл file.txt используйте:
echo test 2> file.txt
Синтаксис >& используется для перенаправления потока в другой дескриптор файла:
- 0 — это stdin (стандартный ввод)
- 1 — это stdout (стандартный вывод)
- 2 — это stderr (стандартный вывод ошибок)
Для перенаправления stdout в stderr можно использовать следующую команду:
echo test 1>&2 # аналогично, можно записать как echo test >&2
Чтобы перенаправить stderr в stdout, выполните:
echo test 2>&1
Таким образом, в конструкции 2>&1:
2>перенаправляет stderr в (неуказанный) файл.&1перенаправляет stderr в stdout.
Номера обозначают файловые дескрипторы (fd).
- Ноль — это
stdin(стандартный ввод) - Один — это
stdout(стандартный вывод) - Два — это
stderr(стандартный вывод ошибок)
2>&1 переадресовывает дескриптор 2 (stderr) в дескриптор 1 (stdout).
Это работает для любого количества файловых дескрипторов, если программа их использует.
Если вы вдруг забудете, можете взглянуть на файл /usr/include/unistd.h:
/* Стандартные файловые дескрипторы. */
#define STDIN_FILENO 0 /* Стандартный ввод. */
#define STDOUT_FILENO 1 /* Стандартный вывод. */
#define STDERR_FILENO 2 /* Стандартный вывод ошибок. */
На эту тему стоит отметить, что я писал инструменты на C, которые используют нестандартные файловые дескрипторы для пользовательского логирования, так что вы их не увидите, если не переадресуете вывод в файл или что-то подобное.
Конструкция 2>&1 перенаправляет стандартный поток ошибок (stderr) в текущее местоположение стандартного вывода (stdout). Этот нюанс, касающийся порядка операций, часто игнорируется в других ответах.
Вы можете перенаправить любой поток вывода на другой с помощью данного метода, но чаще всего он используется для объединения потоков stdout и stderr в один поток для последующей обработки.
Вот несколько примеров:
# Ищем строку ERROR в stdout и stderr.
foo 2>&1 | grep ERROR
# Запускаем просмотрщик less без вмешательства stderr в вывод.
foo 2>&1 | less
# Отправляем stdout и stderr в файл (с добавлением) и терминал.
foo 2>&1 | tee /dev/tty >> outfile
# Направляем stderr в обычное место, а stdout в файл.
foo > outfile1 2>&1 > outfile2
Обратите внимание, что последний пример не перенаправит stderr в outfile2 — он перенаправит его в то место, где находился stdout на момент, когда был встретен аргумент (outfile1), а затем перенаправит stdout в outfile2.
Это позволяет производить довольно изощренные манипуляции с потоками вывода.
2 - это стандартный поток ошибок консоли.
1 - это стандартный поток вывода консоли.
Это стандарт для Unix, и Windows также следует спецификации POSIX.
Например, когда вы выполняете команду:
perl test.pl 2>&1
стандартный поток ошибок перенаправляется в стандартный поток вывода, так что вы можете видеть оба вывода вместе:
perl test.pl > debug.log 2>&1
После выполнения вы сможете увидеть весь вывод, включая ошибки, в файле debug.log.
perl test.pl 1>out.log 2>err.log
В этом случае стандартный вывод будет перенаправлен в out.log, а стандартный поток ошибок - в err.log.
Я рекомендую вам попытаться разобраться в этих механизмах.
Разница между sh и Bash
Как сделать паузу в shell-скрипте на одну секунду перед продолжением?
Bash инструмент для получения n-й строки из файла
Прерывание скрипта оболочки при возвращении любой команды ненулевого значения
Как узнать, в какой интерактивной оболочке я нахожусь (командная строка)