Что означает "2>&1" в оболочке?

в оболочке Unix, если я хочу объединить stderr и stdout на stdout поток для дальнейших манипуляций, я могу добавить следующее В конце моей команды:

2>&1

Итак, если я хочу использовать head на выходе из g++, Я могу сделать что-то вроде этого:

g++ lots_of_errors 2>&1 | head

поэтому я вижу только первые несколько ошибок.

у меня всегда есть проблемы с запоминанием этого, и я постоянно должен идти искать его, и это в основном потому, что я не полностью поймите синтаксис этого трюка.

может кто-то разбить это и объяснить характер по характеру, что 2>&1 означает?

15 ответов


файловый дескриптор 1-это стандартный вывод (stdout).
Файловый дескриптор 2 является стандартной ошибкой (stderr).

вот один из способов запомнить эту конструкцию (хотя это не совсем точно): сначала 2>1 может выглядеть как хороший способ, чтобы перенаправить stderr to stdout. Однако на самом деле это будет интерпретироваться как "redirect stderr в файл с именем 1". & указывает, что ниже приведен файловый дескриптор, а не имя файла. Поэтому конструкция становится: 2>&1.


echo test > afile.txt

перенаправляет stdout в afile.txt. Это то же самое, что делать

echo test 1> afile.txt

чтобы перенаправить stderr, вы:

echo test 2> afile.txt

>& синтаксис для перенаправления потока в другой файловый дескриптор-0-stdin, 1-stdout, а 2-stderr.

вы можете перенаправить stdout на stderr, выполнив:

echo test 1>&2 # or echo test >&2

или наоборот:

echo test 2>&1

так, короче... 2> перенаправляет stderr в (неуказанный) файл, добавляя &1 перенаправляет поток stderr в stdout.


некоторые трюки о перенаправлении

некоторые особенности синтаксиса об этом могут иметь важное поведение. Есть несколько небольших примеров о перенаправлениях,STDERR, STDOUT, и доводы заказ.

1-перезапись или добавление?

символ > mean перенаправление.

  • > mean "отправить" в целом завершена файл, перезапись цели, если она существует (см. noclobber функция bash в #3 позже).
  • >> mean отправить в дополнение к будет добавлен к цели, если существует.

в любом случае, файл будет создан, если они не существуют.

2-The командная строка оболочки зависит от порядка!!

для тестирования этого нам нужно простая команда, которая будет отправлять что-то на обоих выходах:

$ 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 --->

обратите внимание, что последняя командная строка в этом абзаце точно такая же, как и в предыдущем абзаце, где я писал кажется, не ожидаемое поведение (таким образом, это может быть даже ожидаемое поведение).

Ну, есть немного трюков о перенаправлениях, для выполнение различных операций на обоих выходах:

$ ( 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

Примечание: &9 дескриптор произойдет спонтанно из-за ) 9>&2.

добавление: nota! новая версия Баш (>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 к другому и, наконец, оба выхода объединены, проходят через третий командный фильтр.

3 - Слово о и >| синтаксис

вот про перезапись:

пока set -o noclobber поручить баш на не перезаписывает любой существующий файл, то >| синтаксис позволяет вам пройти через это ограничение:

$ 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

4 - последний трюк и больше...

для перенаправление и выход из данной команды, мы видим, что правильный синтаксис может быть:

$ ls -ld /tmp /tnt >/dev/null 2>&1

для этого специальные case, есть синтаксис ярлыка:&> ... или >&

$ ls -ld /tmp /tnt &>/dev/null

$ ls -ld /tmp /tnt >&/dev/null

Примечание: если 2>&1, 1>&2 является правильным синтаксисом:

$ ls -ld /tmp /tnt 2>/dev/null 1>&2

4b-теперь я дам вам подумать о:

$ 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/

4c-если вы заинтересованы в больше информация

вы можете прочитать прекрасное руководство, нажав:

man -Len -Pless\ +/^REDIRECTION bash

на Баш


числа относятся к файловым дескрипторам (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, которые используют нестандартные файловые дескрипторы для пользовательских ведение журнала, чтобы вы не видели его, если вы не перенаправите его в файл или что-то еще.


я нашел этот блестящий пост на перенаправление:Все о перенаправлений

перенаправить стандартный вывод и стандартный поток ошибок в файл

$ command & > file

этот ОДН-вкладыш использует &> оператор для перенаправления обоих выходных потоков-stdout и stderr - из команды в файл. Это ярлык Bash для быстрого перенаправления обоих потоков в один и тот же назначение.

вот как выглядит таблица дескрипторов файлов после того, как Bash перенаправил оба потока:

Enter image description here

как вы можете видеть, как stdout и stderr теперь указывают на file. Поэтому все, что написано в stdout и stderr, записывается в file.

существует несколько способов перенаправления обоих потоков в одно и то же место назначения. Вы можете перенаправлять каждый поток один за другим:

$ command >файл 2>&1

Это гораздо более распространенный способ, чтобы перенаправить потоки в файл. Сначала stdout перенаправляется в файл, а затем stderr дублируется, чтобы быть таким же, как stdout. Таким образом, оба потока в конечном итоге указывают на file.

когда Bash видит несколько перенаправлений, он обрабатывает их слева направо. Давайте пройдем через ступени и посмотрим, как это произойдет. Перед запуском каких-либо команд таблица дескриптора файла Bash выглядит так это:

Enter image description here

теперь Bash обрабатывает первое перенаправление >файл. Мы видели это раньше, и это заставляет stdout указывать на файл:

Enter image description here

Next Bash видит второе перенаправление 2>&1. Мы не видели это перенаправление раньше. Этот дублирует файловый дескриптор 2, чтобы быть копией файлового дескриптора 1, и мы получаем:

Enter image description here

оба потока были перенаправлены в файл.

однако будьте осторожны здесь! Пишу

команда >файл 2>&1

- это не то же самое что писать:

$ command 2>&1 > file

порядок перенаправления имеет значение в Bash! Эта команда перенаправляет в файл только стандартный вывод. Stderr по-прежнему будет печатать на терминале. Чтобы понять, почему это происходит, давайте снова пройдем через шаги. Поэтому перед запуском команды, таблица дескрипторов файлов выглядит следующим образом:

Enter image description here

теперь Bash обрабатывает перенаправления слева направо. Сначала он видит 2>&1, поэтому он дублирует stderr в stdout. Таблица дескрипторов файлов становится:

Enter image description here

теперь Баш видит второе перенаправление,>file, и он перенаправляет stdout в файл:

Enter image description here

вы видите, что здесь происходит? Stdout теперь указывает на файл, но устройство по-прежнему указывает на терминал! Все, что пишется в stderr, по-прежнему распечатывается на экран! Так что будьте очень, очень осторожны с целью перенаправления!

также обратите внимание, что в Bash, написание

$ command & > file

точно так же, как:

$ command > & file


эта конструкция отправляет стандартный поток ошибок (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

обратите внимание, что последний Уилл!--12-->не прямые stderr to outfile2 - он перенаправляет его на то, что stdout был, когда аргумент был обнаружен (outfile1) и затем редиректы stdout to outfile2.

это позволяет некоторые довольно сложные обманы.


2>&1 является конструкцией оболочки POSIX. Вот разбивка, токен за токеном:


2:"Стандартная ошибка" вывода дескриптор файла.

>&: дублировать дескриптор выходного файла оператор (вариант Перенаправление Вывода оператор >). Дано [x]>&[y] дескриптор файла, обозначенного как x является копией дескриптора выходного файла y.

1 "стандартный вывод" вывода дескриптор файла.

выражение 2>&1 копирует файл дескриптора 1 на месте 2, поэтому любой вывод записывается в 2 ("Стандартная ошибка") в среде выполнения переходит в тот же файл, первоначально описанный 1 ("стандарт на выходе").


дальнейших объяснений:

Дескриптор: "уникальный процесс, неотрицательное целое число, используемое для идентификации открытого файла с целью доступа к файлу."

стандартный вывод/ошибка: см. следующее примечание в перенаправление раздел документации оболочки:

открытые файлы представлены десятичными числами, начинающимися с нуля. Наибольшее возможное значение определяется реализацией; однако, все реализации должны поддерживать, по крайней мере, от 0 до 9 включительно, для использования приложения. Эти числа называются "файловыми дескрипторами". Значения 0, 1 и 2 имеют особое значение и обычное использование и подразумеваются определенными операциями перенаправления; они называются стандартным входом, стандартным выходом и стандартной ошибкой соответственно. Программы обычно занимают свои входные данные из стандартного ввода и выводить на стандартный вывод. Сообщения об ошибках обычно записываются на стандартную ошибку. Операторам перенаправления может предшествовать одна или несколько цифр (без промежуточных символов разрешено) для обозначения номера дескриптора файла.


чтобы ответить на ваш вопрос: он принимает любой вывод ошибок (обычно отправляется в stderr) и записывает его в стандартный вывод (stdout).

Это полезно, например, "больше", когда вам нужна подкачка для всех выходных данных. Некоторые программы, такие как печать информации об использовании в поток stderr.

, чтобы помочь вам запомнить

  • 1 = стандартный выход (где программы печатают нормальный выход)
  • 2 = Стандартная ошибка (где программы печати ошибки)

"2>&1" просто указывает все, отправленное в stderr, в stdout вместо этого.

Я также рекомендую читать это сообщение об ошибке перенаправления где эта тема рассматривается в полной мере.


2 Стандартная ошибка консоли.

1-стандартный вывод на консоль.

Это стандартный Unix, и Windows также следует за POSIX.

Е. Г. при запуске

perl test.pl 2>&1

Стандартная ошибка перенаправляется на стандартный вывод, поэтому вы можете видеть оба вывода вместе:

perl test.pl > debug.log 2>&1

после выполнения вы можете увидеть все выходные данные, включая ошибки, в отладке.бревно.

perl test.pl 1>out.log 2>err.log

затем стандартный выход из.журнал и стандартная ошибка для ошибки.бревно.

Я предлагаю вам попытаться понять это.


С точки зрения программиста, это означает именно это:

dup2(1, 2);

посмотреть man page.

понимая, что 2>&1 - это скопировать также объясняет, почему ...

command >file 2>&1

... не совпадает ...

command 2>&1 >file

первый отправит оба потока в file, тогда как второй будет отправить ошибки stdout, и обычный выход на file.


люди, всегда помню paxdiabloнамек на настоящее расположение цели перенаправления... Это is важно.

моя личная мнемоника для 2>&1 оператор это:

  • думать & означает 'and' или 'add' (символ ампер-и, не так ли?)
  • так это будет: 'redirect 2 (поток stderr), где 1 (поток stdout) уже/в настоящее время и добавить оба потока'.

та же мнемоника работает и для другого часто используемого перенаправления,1>&2:

  • думать & смысл and или add... (у вас есть идея насчет амперсанда, да?)
  • так это будет: 'redirect 1 (stdout) куда 2 (поток stderr) уже/в настоящее время и добавить как ручьи!--14-->.

и всегда помните: вы должны прочитать цепей перенаправления с конца, справа налево (не слева направо).


при условии, что /foo не существует в вашей системе и /tmp нет...

$ ls -l /tmp /foo

напечатает содержимое /tmp и печатать сообщение об ошибке для /foo

$ ls -l /tmp /foo > /dev/null

вышлю содержимое /tmp to /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

стенография


Это так же, как передача ошибки в stdout или терминал.

то есть cmd Не команду:

$cmd 2>filename
cat filename

command not found

ошибка отправляется в файл следующим образом:

2>&1

Стандартная ошибка отправляется на терминал.


Перенаправления Ввода

перенаправление ввода вызывает файл, имя которого результаты расширения word, который будет открыт для чтения в файле дескриптор n или стандартный ввод (файловый дескриптор 0), если n не указан.

общий формат для перенаправления ввода:

[n]<word

Перенаправление Вывода

перенаправление вывода вызывает файл, имя является результатом расширения word to be открыт для записи файловый дескриптор n или стандартный вывод (файловый дескриптор 1), Если n не уточняется. Если файл не существует, он создается; если он существует, он усекается до нулевого размера.

общий формат для перенаправления вывода:

[n]>word

Перемещение Дескрипторов Файлов

оператор перенаправления,

[n]<&digit-

перемещает цифру файлового дескриптора в файловый дескриптор n или стандартный ввод (файл дескриптор 0), если N не указано. цифра закрывается после дублирования до n.

аналогично, оператор перенаправления

[n]>&digit-

перемещает цифру файлового дескриптора в файловый дескриптор n или стандартный вывод (файловый дескриптор 1), Если n не указано.

Ref:

man bash

тип /^REDIRECT для найдите redirection раздел и узнать больше...

онлайн-версия здесь: 3.6 Редиректы

PS:

много времени, man был мощным инструментом для изучения Linux.


0 для входного сигнала, 1 для stdout и 2 для stderr.

Один Совет: somecmd >1.txt 2>&1, а не somecmd 2>&1 >1.txt полностью неправильно нет эффекта!