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

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

2>&1

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

g++ lots_of_errors 2>&1 | head

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

Мне всегда трудно запомнить это, и мне постоянно нужно искать его, и это связано главным образом с тем, что я не полностью понимаю синтаксис этого конкретного трюка. Может кто-то сломать это и объяснить персонажа по характеру, что означает "2 > и 1"?

1554
04 мая '09 в 1:57
источник поделиться
16 ответов

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

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

1763
04 мая '09 в 2:04
источник
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

436
04 мая '09 в 1:59
источник

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

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

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

Символ > означает перенаправление.

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

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

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

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

$ 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! С новой версией (>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 - Слово о 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

4 - Последний трюк и многое другое...

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

$ 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

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

в console; )

228
29 апр. '13 в 19:33
источник
  • 2 является файловым дескриптором по умолчанию для stderr.
  • 1 является файловым дескриптором по умолчанию для stdout.
  • >& - это синтаксис оболочки для "свернуть предыдущий (первый) файловый дескриптор в будущий (второй) файловый дескриптор".
112
03 дек. '17 в 1:38

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

59
04 мая '09 в 1:58
источник

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

Это позволяет использовать довольно сложный обман.

45
04 мая '09 в 2:54
источник

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

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

$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

26
29 окт. '16 в 16:04
источник

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.

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

12
19 июля '13 в 6:23
источник

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

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

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

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

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

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

12
04 мая '09 в 2:24
источник

2>&1 - это конструкция оболочки POSIX. Вот разбивка, токен с помощью токена:


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

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

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

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


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

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

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

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

10
25 дек. '16 в 9:43
источник

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

dup2(1, 2);

См. справочную страницу .

Понимание того, что 2>&1 является копией, также объясняет, почему...

command >file 2>&1

... не то же самое, что...

command 2>&1 >file

Первый отправит оба потока в file, а второй отправит ошибки в stdout, а обычный вывод - в file.

8
03 дек. '15 в 13:20
источник

Люди всегда помнят paxdiablo о местоположении текущего адреса перенаправления... Важно .

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

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

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

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

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

4
01 июля '12 в 13:47
источник

Это точно так же, как paasing ошибка для stdout или терминала. т.е. cmd не команда $ cmd 2 > filename cat filename команда не найдена

Ошибка, отправленная в файл, подобный этому 2 > & 1 ошибка, отправленная на терминал

4
11 окт. '13 в 9:16
источник

Если /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

является сокращением

2
01 сент. '16 в 23:58
источник

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

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

2
06 июня '15 в 14:07
источник

0 для ввода, 1 для stdout и 2 для stderr.

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

0
25 июля '16 в 12:46
источник

Посмотрите другие вопросы по меткам или Задайте вопрос