В оболочке Unix, если я хочу объединить stderr
и stdout
в поток stdout
для дальнейшей обработки, я могу добавить следующее в конце моей команды:
2>&1
Итак, если я хочу использовать "head" на выходе из g++, я могу сделать что-то вроде этого:
g++ lots_of_errors 2>&1 | head
поэтому я вижу только первые несколько ошибок.
Мне всегда трудно запомнить это, и мне постоянно нужно искать его, и это связано главным образом с тем, что я не полностью понимаю синтаксис этого конкретного трюка. Может кто-то сломать это и объяснить персонажа по характеру, что означает "2 > и 1"?
Дескриптор файла 1 - это стандартный вывод (stdout).
Дескриптор файла 2 является стандартной ошибкой (stderr).
Вот один из способов запомнить эту конструкцию (хотя это не совсем точно): сначала 2>1
может выглядеть как хороший способ перенаправления stderr на stdout. Однако на самом деле это будет интерпретироваться как "перенаправить stderr в файл с именем 1
". &
указывает, что следующим является файловый дескриптор, а не имя файла. Таким образом, конструкция становится: 2>&1
.
java... 2&1 >> data.log
, я видел, как один из моих коллег сделал это?
echo test > afile.txt
.. перенаправляет stdout на afile.txt
. Это то же самое, что и делать.
echo test 1> afile.txt
Чтобы перенаправить stderr, вы...
echo test 2> afile.txt
>&
- это синтаксис для перенаправления потока в другой дескриптор файла - 0 - это stdin. 1 - стандартный вывод. 2 - stderr.
Вы можете перенаправить stdout на stderr, выполнив..
echo test 1>&2 # or echo test >&2
.. или наоборот:
echo test 2>&1
Итак, короче.. 2>
перенаправляет stderr в (неуказанный) файл, добавляя &1
перенаправляет stderr в stdout
java ... 2&1 >> data.log
, я видел, как один из моих коллег сделал это?
cmd 2>&1 >> somefile.log
добавит stdout / stderr в файл - он в основном такой же, как и выше, с >> file
для добавления
Некоторые особенности синтаксиса в этом могут иметь важное поведение. Существует несколько небольших примеров перенаправления, STDERR
, STDOUT
и аргументов упорядочение.
Символ >
означает перенаправление.
>
означает отправку в целом завершенный файл, переписывание цели, если существует (см. noclobber
bash функция на # 3 позже).>>
означает, что отправка будет добавлена к целевому, если существует.В любом случае файл будет создан, если он не существует.
Для тестирования этого нам нужна простая команда, которая будет посылать что-то на оба выхода:
$ ls -ld /tmp /tnt
ls: cannot access /tnt: No such file or directory
drwxrwxrwt 118 root root 196608 Jan 7 11:49 /tmp
$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory
$ ls -ld /tmp /tnt 2>/dev/null
drwxrwxrwt 118 root root 196608 Jan 7 11:49 /tmp
(Ожидается, что у вас нет каталога с именем /tnt
, конечно;). Ну, у нас есть это!
Итак, давайте посмотрим:
$ ls -ld /tmp /tnt >/dev/null
ls: cannot access /tnt: No such file or directory
$ ls -ld /tmp /tnt >/dev/null 2>&1
$ ls -ld /tmp /tnt 2>&1 >/dev/null
ls: cannot access /tnt: No such file or directory
Последняя дамп командной строки STDERR
на консоли, похоже, не ожидаемое поведение... Но...
Если вы хотите сделать некоторую фильтрацию сообщений примерно на один вывод, другой или оба:
$ ls -ld /tmp /tnt | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory
<-- drwxrwxrwt 118 root root 196608 Jan 7 12:02 /tmp --->
$ ls -ld /tmp /tnt 2>&1 | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->
<-- drwxrwxrwt 118 root root 196608 Jan 7 12:02 /tmp --->
$ ls -ld /tmp /tnt >/dev/null | sed 's/^.*$/<-- & --->/'
ls: cannot access /tnt: No such file or directory
$ ls -ld /tmp /tnt >/dev/null 2>&1 | sed 's/^.*$/<-- & --->/'
$ ls -ld /tmp /tnt 2>&1 >/dev/null | sed 's/^.*$/<-- & --->/'
<-- ls: cannot access /tnt: No such file or directory --->
Обратите внимание, что последняя команда в этом параграфе точно такая же, как в предыдущей парагафе, где я писал, похоже, не является ожидаемым поведением (так что это может быть даже ожидаемое поведение).
Ну, есть несколько трюков о перенаправлении, для выполняет разные операции над обеими ouputs:
$ ( ls -ld /tmp /tnt | sed 's/^/O: /' >&9 ) 9>&2 2>&1 | sed 's/^/E: /'
O: drwxrwxrwt 118 root root 196608 Jan 7 12:13 /tmp
E: ls: cannot access /tnt: No such file or directory
Nota: дескриптор &9
будет возникать спонтанно из-за ) 9>&2
.
Добавление: nota! С новой версией bash (>4.0
) появилась новая функция и более сексуальный синтаксис для выполнения таких действий:
$ ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /')
O: drwxrwxrwt 17 root root 28672 Nov 5 23:00 /tmp
E: ls: cannot access /tnt: No such file or directory
И окончательно для такого каскадного форматирования вывода:
$ ((ls -ld /tmp /tnt |sed 's/^/O: /' >&9 ) 2>&1 |sed 's/^/E: /') 9>&1| cat -n
1 O: drwxrwxrwt 118 root root 196608 Jan 7 12:29 /tmp
2 E: ls: cannot access /tnt: No such file or directory
Добавление: nota! Тот же новый синтаксис в обоих направлениях:
$ cat -n <(ls -ld /tmp /tnt 2> >(sed 's/^/E: /') > >(sed 's/^/O: /'))
1 O: drwxrwxrwt 17 root root 28672 Nov 5 23:00 /tmp
2 E: ls: cannot access /tnt: No such file or directory
Где STDOUT
проходит через конкретный фильтр, STDERR
в другой, и, наконец, оба выхода, объединенные, проходят через третий командный фильтр.
noclobber
и синтаксисе >|
Что о перезаписывать:
Пока set -o noclobber
инструктирует bash to not перезаписать любой существующий файл, синтаксис >|
позволяет вам пройти это ограничение:
$ testfile=$(mktemp /tmp/testNoClobberDate-XXXXXX)
$ date > $testfile ; cat $testfile
Mon Jan 7 13:18:15 CET 2013
$ date > $testfile ; cat $testfile
Mon Jan 7 13:18:19 CET 2013
$ date > $testfile ; cat $testfile
Mon Jan 7 13:18:21 CET 2013
Файл перезаписывается каждый раз, ну теперь:
$ set -o noclobber
$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan 7 13:18:21 CET 2013
$ date > $testfile ; cat $testfile
bash: /tmp/testNoClobberDate-WW1xi9: cannot overwrite existing file
Mon Jan 7 13:18:21 CET 2013
Пройдите с помощью >|
:
$ date >| $testfile ; cat $testfile
Mon Jan 7 13:18:58 CET 2013
$ date >| $testfile ; cat $testfile
Mon Jan 7 13:19:01 CET 2013
Отсоединение этой опции и/или запрос, если он уже установлен.
$ set -o | grep noclobber
noclobber on
$ set +o noclobber
$ set -o | grep noclobber
noclobber off
$ date > $testfile ; cat $testfile
Mon Jan 7 13:24:27 CET 2013
$ rm $testfile
Для перенаправления обоих вывода из данной команды мы видим, что правильный синтаксис может быть:
$ ls -ld /tmp /tnt >/dev/null 2>&1
для этого частного случая существует синтаксис ярлыка: &>
... или >&
$ ls -ld /tmp /tnt &>/dev/null
$ ls -ld /tmp /tnt >&/dev/null
Nota: если 2>&1
существует, 1>&2
также является правильным синтаксисом:
$ ls -ld /tmp /tnt 2>/dev/null 1>&2
$ ls -ld /tmp /tnt 2>&1 1>&2 | sed -e s/^/++/
++/bin/ls: cannot access /tnt: No such file or directory
++drwxrwxrwt 193 root root 196608 Feb 9 11:08 /tmp/
$ ls -ld /tmp /tnt 1>&2 2>&1 | sed -e s/^/++/
/bin/ls: cannot access /tnt: No such file or directory
drwxrwxrwt 193 root root 196608 Feb 9 11:08 /tmp/
вы можете прочитать "Изящное руководство", нажав:
man -Len -Pless\ +/^REDIRECTION bash
в bash console; )
>&
- это синтаксис оболочки для "свернуть предыдущий (первый) файловый дескриптор в будущий (второй) файловый дескриптор".Цифры относятся к дескрипторам файла (fd).
stdin
stdout
stderr
2>&1
перенаправляет fd 2 в 1.
Это работает для любого количества файловых дескрипторов, если программа использует их.
Вы можете посмотреть /usr/include/unistd.h
, если вы забудете их:
/* Standard file descriptors. */
#define STDIN_FILENO 0 /* Standard input. */
#define STDOUT_FILENO 1 /* Standard output. */
#define STDERR_FILENO 2 /* Standard error output. */
Тем не менее, я написал инструменты C, которые используют нестандартные дескрипторы файлов для пользовательского ведения журнала, поэтому вы не видите его, если вы не перенаправляете его на файл или что-то в этом роде.
Эта конструкция отправляет стандартный поток ошибок (stderr
) в текущее местоположение стандартного вывода (stdout
) - эта проблема с валютой, по-видимому, игнорировалась другими ответами.
Вы можете перенаправить любой дескриптор вывода на другой с помощью этого метода, но чаще всего он используется для направления потоков stdout
и stderr
в один поток для обработки.
Некоторые примеры:
# Look for ERROR string in both stdout and stderr.
foo 2>&1 | grep ERROR
# Run the less pager without stderr screwing up the output.
foo 2>&1 | less
# Send stdout/err to file (with append) and terminal.
foo 2>&1 |tee /dev/tty >>outfile
# Send stderr to normal location and stdout to file.
foo >outfile1 2>&1 >outfile2
Обратите внимание, что этот последний не будет перенаправлять stderr
на outfile2
- он перенаправляет его на то, что stdout
было, когда аргумент был встречен (outfile1
), а затем перенаправляет stdout
в outfile2
.
Это позволяет использовать довольно сложный обман.
Я нашел этот блестящий пост в перенаправлении: Все о перенаправлениях
Перенаправить как стандартный вывод, так и стандартную ошибку в файл
$command & > file
Этот однострочный оператор использует оператор & > для перенаправления обоих выходных потоков - stdout и stderr - из команды в файл. Это bash ярлык для быстрого перенаправления обоих потоков в один и тот же пункт назначения.
Вот как выглядит таблица дескриптора файла после того, как bash перенаправил оба потока:
Как вы можете видеть, как stdout, так и stderr теперь указывают на файл. Итак, все, что написано в stdout и stderr, записывается в файл.
Существует несколько способов перенаправления обоих потоков в один и тот же пункт назначения. Вы можете перенаправлять каждый поток один за другим:
$command > файл 2 > & 1
Это гораздо более распространенный способ перенаправления обоих потоков в файл. Сначала stdout перенаправляется в файл, а затем stderr дублируется так же, как stdout. Таким образом, оба потока в конечном итоге указывают на файл.
Когда bash видит несколько перенаправлений, он обрабатывает их слева направо. Пройдите через шаги и посмотрите, как это происходит. Перед запуском любых команд bash таблица дескрипторов файлов выглядит следующим образом:
Теперь bash обрабатывает первый файл перенаправления > . Мы видели это раньше, и это делает stdout точкой для файла:
Далее bash видит второе перенаправление 2 > & 1. Мы не видели этого перенаправления раньше. Этот дубликат файлового дескриптора 2 является копией файлового дескриптора 1, и мы получаем:
Оба потока были перенаправлены в файл.
Однако будьте осторожны! Запись:
command > file 2 > & 1
Это не то же самое, что писать:
$command 2 > & 1 > file
Порядок перенаправления имеет значение bash! Эта команда перенаправляет только стандартный вывод в файл. Stderr все равно будет печататься на терминале. Чтобы понять, почему это происходит, повторите шаги. Поэтому перед запуском команды таблица дескриптора файла выглядит следующим образом:
Теперь bash обрабатывает перенаправления слева направо. Сначала он видит 2 > & 1, поэтому он дублирует stderr на stdout. Таблица дескрипторов файлов:
Теперь bash видит второй файл перенаправления > и перенаправляет stdout в файл:
Вы видите, что здесь происходит? Stdout теперь указывает на файл, но stderr все еще указывает на терминал! Все, что записывается в stderr, все равно печатается на экране! Так что будьте очень осторожны с порядком перенаправления!
Также обратите внимание, что в bash, написав это:
$command & > file
Точно так же, как:
$command > & file
>&
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.
Я предлагаю вам попытаться понять их.
perl test.pl > debug.log 2>&1
Чтобы ответить на ваш вопрос: он принимает любой вывод ошибки (обычно отправляется в stderr) и записывает его на стандартный вывод (stdout).
Это полезно, например, "больше", когда вам нужен пейджинг для всего вывода. Некоторые программы, такие как печать информации об использовании в stderr.
Чтобы помочь вам запомнить
"2 > & 1" просто указывает все, отправленные в stderr, вместо stdout.
Я также рекомендую прочитать этот пост при перенаправлении ошибок, где этот вопрос подробно освещен.
2>&1
- это конструкция оболочки POSIX. Вот разбивка, токен с помощью токена:
2
: дескриптор выходного файла Стандартная ошибка.
>&
: Дублировать дескриптор выходного файла (вариант Перенаправление вывода оператор >
). Учитывая [x]>&[y]
, дескриптор файла, обозначенный x
, делается копией дескриптора выходного файла y
.
1
" Стандартный вывод" дескриптор выходного файла.
Выражение 2>&1
копирует дескриптор файла 1
в location 2
, поэтому любой вывод, записанный в 2
( "стандартная ошибка" ) в среде выполнения, переходит в тот же файл, который был первоначально описан 1
( "стандартный вывод" ).
Дальнейшее объяснение:
Дескриптор файла: "Уникальное целое число для каждого процесса, используемое для идентификации открытого файла для цель доступа к файлам."
Стандартный вывод/ошибка. Обратитесь к следующему примечанию в разделе Redirection документации оболочки:
Открытые файлы представлены десятичными числами, начиная с нуля. Наибольшее возможное значение определяется реализацией; однако все реализации должны поддерживать как минимум от 0 до 9 включительно для использования в приложении. Эти числа называются "файловыми дескрипторами". Значения 0, 1 и 2 имеют особое значение и обычное использование и подразумеваются некоторыми операциями перенаправления; они называются стандартным входом, стандартным выходом и стандартной ошибкой, соответственно. Обычно программы берут свой вход со стандартного ввода и записывают вывод на стандартный вывод. Сообщения об ошибках обычно записываются по стандартной ошибке. Операторам перенаправления может предшествовать одна или несколько цифр (без промежуточных символов) для обозначения номера дескриптора файла.
С точки зрения программиста это означает именно это:
dup2(1, 2);
См. справочную страницу .
Понимание того, что 2>&1
является копией, также объясняет, почему...
command >file 2>&1
... не то же самое, что...
command 2>&1 >file
Первый отправит оба потока в file
, а второй отправит ошибки в stdout
, а обычный вывод - в file
.
Это точно так же, как paasing ошибка для stdout или терминала. т.е. cmd не команда $ cmd 2 > filename cat filename команда не найдена
Ошибка, отправленная в файл, подобный этому 2 > & 1 ошибка, отправленная на терминал
Люди всегда помнят paxdiablo о местоположении текущего адреса перенаправления... Важно .
Моя личная мнемоника для оператора 2>&1
такова:
&
как о значении 'and'
или 'add'
(символ имеет значение ampers- и, не так ли?)2
(stderr), где 1
(stdout) уже/в настоящее время и добавить оба потока.Эта же мнемоника работает и для другого часто используемого перенаправления, 1>&2
:
&
значение and
или add
... (вы поняли идею амперсанда, да?)1
(stdout), где 2
(stderr) уже/в настоящее время и добавить оба потока.И всегда помните: вам нужно читать цепочки перенаправления "от конца", справа налево ( не слева направо).
Если /foo
не существует в вашей системе и /tmp
делает...
$ ls -l /tmp /foo
напечатает содержимое /tmp
и напечатает сообщение об ошибке для /foo
$ ls -l /tmp /foo > /dev/null
отправит содержимое /tmp
в /dev/null
и напечатает сообщение об ошибке для /foo
$ ls -l /tmp /foo 1> /dev/null
будет делать то же самое (обратите внимание на 1)
$ ls -l /tmp /foo 2> /dev/null
напечатает содержимое /tmp
и отправит сообщение об ошибке на /dev/null
$ ls -l /tmp /foo 1> /dev/null 2> /dev/null
отправит как листинг, так и сообщение об ошибке на /dev/null
$ ls -l /tmp /foo > /dev/null 2> &1
является сокращением
Перенаправление ввода
Перенаправление ввода вызывает файл, имя которого результаты расширения слова, которое нужно открыть для чтения в файле дескриптор n или стандартный ввод (дескриптор файла 0), если n является не указано.
Общий формат для перенаправления ввода:
[n]<word
Перенаправление вывода
Перенаправление вывода вызывает файл, чей имя вытекает из расширения слова, которое нужно открыть для написания дескриптор файла n или стандартный вывод (дескриптор файла 1), если n не указывается. Если файл не существует, он создается; если оно существует, он усечен до нулевого размера.
Общий формат для перенаправления вывода:
[n]>word
Перемещение дескрипторов файлов
Перемещение дескрипторов файлов Оператор перенаправления
[n]<&digit-
перемещает номер дескриптора файла в дескриптор файла n или стандартный ввод (дескриптор файла 0), если n не указано. цифра закрывается после дублирования с n.
Аналогично, оператор перенаправления
[n]>&digit-
перемещает номер дескриптора файла в дескриптор файла n или стандартный вывод (дескриптор файла 1), если n не указано.
man bash
введите /^REDIRECT
, чтобы найти раздел redirection
, узнать подробнее..
онлайн-версия здесь:
http://www.gnu.org/software/bash/manual/bashref.html#Redirections
много времени, man
был мощным инструментом для изучения linux
0 для ввода, 1 для stdout и 2 для stderr.
Один совет:
somecmd >1.txt 2>&1
является правильным, а somecmd 2>&1 >1.txt
полностью неправильным без эффекта!