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

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

04.05.2009 02:57:00 Просмотров 28 Источник

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

2>&1

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

g++ lots_of_errors 2>&1 | head

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

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

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

У вопроса есть решение - Посмотреть?

https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean#comment627563_818255
@dbr я не думаю, что это просто bash - я считаю, что это ракушка Борна; следовательно, sh, bash, ksh, ash, dash и т. д.
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean#comment22471442_818255
Это часть параграфа перенаправления, описывающего POSIX-совместимые оболочки, или POSIX shell для краткости. например, ksh - это оболочка POSIX. Смотрите: pubs.opengroup.org/onlinepubs/009695399/utilities/…
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean#comment28957255_818255
Эта конструкция также работает на Windows.
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean#comment89828592_818255
вы можете проверить этот ответ stackoverflow.com/questions/10508843/what-is-dev-null-21/…

Ответы - В оболочке, что означает "2>&1"? / In the shell, what does " 2>&1 " mean?

Colin Burnett

04.05.2009 02:58:41

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

dbr

04.05.2009 02:59:33

echo test > afile.txt

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

echo test 1> afile.txt

Чтобы перенаправить stderr, вы делаете:

echo test 2> afile.txt

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

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

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

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

echo test 2>&1

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

https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/818265#comment8124138_818265
есть ли в этом какой-то смысл для тебя, java ... 2&1 >> data.log, я видел, как один из моих коллег сделал это?
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/818265#comment8127726_818265
@Гарри, который выглядит как раковина, что не bash, или опечатка.. cmd 2>&1 >> somefile.logдобавит stdout/stderr в файл-это в основном то же самое, что и выше, с >> fileto append
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/818265#comment25874973_818265
@dbr cmd 2>&1 >>fileне перенаправляет stderr в файл, но cmd >> file 2>&1делает. Порядок имеет значение. В первом случае stderr перенаправляется в stdout оболочки (возможно, tty, если команда вводится интерактивно), а затем stdout направляется в файл. Во втором случае stdout направляется в файл, а затем stderr направляется туда же.
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/818265#comment47547366_818265
Мне нравится ответ выше, но он может быть немного яснее. "2>&1" перенаправляет stderr к цели stdout. Поэтому, если у вас есть что-то вроде "ls-l >>> directoryContents 2>>>&1", результатом будет файл с именем directoryContents, к которому будет добавлено содержимое рабочего каталога. При возникновении ошибок в процессе выполнения: сообщения об ошибках будут также добавляться в файл directoryContents по мере их возникновения.
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/818265#comment88298212_818265
Является 0(or 1,2)>&0(or 1,2)возможностью управления выходом? Это echo test >test.log 2>&1 так же, как echo test 2>&1 >test.log?
Является ответом!
Ayman Hourieh

04.05.2009 03:04:53

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

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

https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/818284#comment8124151_818284
есть ли в этом какой-то смысл для тебя, java... 2&1 >> data.log, я видел, как один из моих коллег сделал это?
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/818284#comment9934921_818284
> > > означает добавить выходные данные к данным.журнал.
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/818284#comment19984611_818284
@ThangPham имею в виду стандартный вывод добавляется к данным.журнал и бросила поток stderr в stdout (или консоли следующей команды) см. Мой ответ
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/818284#comment25334547_818284
По-моему, это точно. Как это "не совсем точно"?
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/818284#comment27386353_818284
но тогда не лучше ли будет &2>&1?
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/818284#comment32269807_818284
@Dominik: нет, &интерпретируется только как "файловый дескриптор" в контексте перенаправления. Написание command &2>&разбирается как command &и 2>&1, то есть"выполнить commandв фоновом режиме, затем выполнить команду 2и перенаправить ее stdout в свой stdout".
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/818284#comment36432472_818284
Почему они выбрали такую загадочную вещь, как эта? Просто любопытно.
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/818284#comment42067716_818284
Но как бы вы перенаправили stderr в файл с именем '&1'?
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/818284#comment59623444_818284
@Martin: 2>'&1'
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/818284#comment79886604_818284
есть идеи, почему это взаимодействует с подсветкой grep? nginx -V 2>&1 | grep auth_request, выделяет слово auth_request красным цветом, но nginx -V | grep auth_requestэтого не делает
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/818284#comment83378943_818284
Итак, & значения дескриптора файла, а также перейти в фоновый режим?? Linux должен перестать использовать один и тот же символ слишком запутанно!!
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/818284#comment87387119_818284
В случае, если это помогает для мнемоники для кого-то, как я думаю это связано с языком C & оператора, "адрес" -- так, 2>&1 в целом я прочитал в моей голове, как нечто, напоминающее "(файлового дескриптора) 2 переадресует на адрес (файловый дескриптор) 1". То есть туда , куда в данный момент направляется fd1, начиная с того момента, когда оболочка считывает эту 4-символьную последовательность. (Потому что это может измениться. Для начала, попробовать: ((echo 1/stdout; echo 2/stderr >&2) 2>&1 > /dev/tty) | grep --color .- он раскрасит то, что начиналось как стандартная ошибка ("2/stderr").)
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/818284#comment91006357_818284
Что произойдет, если я сделаю 2> &1(пробел после >) вместо 2>&1? Я не испытываю его сам из-за страха сломать материал.
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/818284#comment98623551_818284
@radiantshaw он просто выдает сообщение об ошибке. В bash: foo 2>&1выводит "- bash: foo: команда не найдена", а foo 2> &1выводит "- bash: синтаксическая ошибка рядом с неожиданным маркером'&'". Оболочки часто придирчивы к пробелам вокруг символов. @Aaron Franke да, foo 2>\&1создает новый файл с именем "&1", содержащий приведенный выше текст ошибки.
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/818284#comment103077230_818284
почему вы сказали, что это не совсем точно? Какую деталь ты перепрыгнул?
Andrioid

04.05.2009 03:24:58

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

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

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

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

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

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

paxdiablo

04.05.2009 03:54:30

Эта конструкция отправляет поток стандартных ошибок (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), а затем перенаправляет outfile2на stderr.

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

https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/818368#comment627606_818368
Хотя этот последний пример был бы намного яснее, как: foo >outfile2 2> > outfile1
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/818368#comment627612_818368
Яснее, да, но это не покажет "позиционную" природу перенаправления. Пример надуман, поскольку обычно это не полезно делать в одной строке-метод становится действительно полезным, когда разные стороны отвечают за разные части перенаправления. Например, когда скрипт выполняет один бит перенаправления, а вы запускаете его с другим битом.
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/818368#comment19279422_818368
Я только что понял, что последний пример также разрешает давнюю путаницу, которую я имел относительно того, почему это: some_program 2>&1 > /dev/nullне работает так: some_program > /dev/null 2>&1.
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/818368#comment86806297_818368
Ваш комментарий к последнему примеру стоит своих золотых букв: -) я никогда не думал, что эти аргументы переадресации являются позиционными... Я думаю, что это очень важно знать.
Kurt Pfeifle

01.07.2012 02:47:27

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

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

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

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

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

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

F. Hauri

29.04.2013 08:33:06

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

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

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

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

  • >mean отправить в целом завершенный файл, перезаписывая цель, если она существует (см. noclobberbash feature на #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 --->

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

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

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

Добавление: нота! С новой версией (>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

Добавление: нота! Тот же новый синтаксис, в обоих направлениях:

$ 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

Речь идет о перезаписи:

В то время >|предписывает bash не перезаписывать ни один существующий файл, синтаксис 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

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

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

$ 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 существует, 2>&1также является правильным синтаксисом:

1>&2

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

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

4c - если вас интересует дополнительная информация

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

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

в консоли ;-)

Marcus Thornton

19.07.2013 07:23:44

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

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

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

https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/17737605#comment45202479_17737605
Второй образец не так: как приоритет стандартный поток ошибок перенаправляется в стандартный поток вывода, стандартный поток stdout будет написано для отладки.log (не STDERR) смотрите мой ответ (абзац №2)! Чтобы гарантировать, что оба будут перенаправлены в один и тот же файл, вы должны инвертировать директивы перенаправления: perl test.pl > debug.log 2>&1
Kalanidhi

11.10.2013 10:16:38

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

То есть cmd-это не команда:

$cmd 2>filename
cat filename

command not found

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

2>&1

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

yurenchen

06.06.2015 02:07:35

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

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

Онлайн-версия находится здесь: 3.6 перенаправления

ПС:

Большую часть времени manбыл мощным инструментом для изучения Linux.

ams

03.12.2015 01:20:34

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

dup2(1, 2);

Смотрите на главной странице .

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

command >file 2>&1

... это не одно и то же...

command 2>&1 >file

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

fzyzcjy

25.07.2016 12:46:19

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

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

Matijs

01.09.2016 11:58:04

При условии, что /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

это стенография

Deen John

29.10.2016 04:04:32

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

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

$ командный файл

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

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

Enter image description here

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

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

$ command > file 2> > &1

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

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

Enter image description here

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

Enter image description here

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

Enter image description here

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

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

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

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

$ command 2>&1 > > файл

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

Enter image description here

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

Enter image description here

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

Enter image description here

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

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

$ командный файл

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

$ командный файл

https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/40319372#comment70799573_40319372
Последние два отличаются, если "команда" заканчивается числом, как тогда, что берется в качестве необязательного файлового дескриптора для >&
https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean/40319372#comment100792729_40319372
Очень хороший рисунок и объяснение! Не могли бы Вы уточнить, что на самом деле означает "дубликат"? Вы упомянули: "этот [2>&1] дублирует файловый дескриптор 2, чтобы быть копией файлового дескриптора 1". Похоже, что stderr дублируется в stdout. Но если это так, должен ли я также видеть err though /dev/tty0?
wjordan

25.12.2016 09:43:43

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


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

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

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

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


Дополнительное разъяснение:

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

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

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

tfmontague

25.01.2020 11:50:25

unix_commands 2>&1

Это используется для вывода ошибок на терминал.

Ниже приведен пример этого процесса

  • При возникновении ошибок они записываются в стандартный адрес памяти ошибок &2"буфер", на который ссылается стандартный поток ошибок 2.
  • Когда вывод производится, он записывается в стандартный выходной адрес памяти &1"буфер", из которого ссылается стандартный выходной поток 1.

Поэтому возьмите unix_commandsи перенаправьте 2, чтобы они были переданы на терминал и напечатаны.

Закрыть X