32

Я сталкивался с несколькими командами, которые используют 2>&1 и 1>&2 , но я совершенно не могу понять, как использовать его и когда мне следует его использовать.

Что я понимаю

Я знаю, что 1 представляет стандартное значение, а 2 представляет стандартную ошибку. Я понимаю, что 2>&1 объединяет выходные данные от 2 до 1 и наоборот.

Что я не получаю

  1. Когда я должен использовать это?
  2. Какой цели это служит?

8 ответов8

35

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


Например, если вы хотите записать как stdout, так и stderr в один и тот же файл (будь то /dev/null или output.txt), вы можете перенаправить их отдельно, с помощью

app 1>/dev/null 2>/dev/null

или вы можете перенаправить один файловый дескриптор в файл, а другой файловый дескриптор - в первый:

app 1>/dev/null 2>&1

app 2>/dev/null 1>&2

В первом примере 2>&1 указывает файловый дескриптор # 2 на то место, где # 1 уже указывает. Второй пример достигает того же самого, просто вместо этого начинается с stderr.

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

out=$(app 2>&1)

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

app 2>&1 | grep hello

Как узнать, какой из 2>&1 или 1>&2 является правильным? Уже настроенный дескриптор файла идет справа от >& , а дескриптор файла, который вы хотите перенаправить, идет влево. (2>&1 означает «указать дескриптор файла № 2 на дескриптор файла № 1».)


Некоторые оболочки имеют ярлыки для общего перенаправления; Вот примеры из Bash:

  • 1> можно сократить до >

  • 1>foo 2>&1 to >&foo или &>foo

  • 2>&1 | program на |& program

2

Иногда вы хотите перенаправить как stdout (1), так и stderr (2) в одно и то же место (например, /dev/null). Одним из способов достижения этого будет:

$ program 1>/dev/null 2>/dev/null

Но большинство людей сокращают это, перенаправляя stderr в stdout с помощью 2>&1:

$ program 1>/dev/null 2>&1

Еще более короткая версия:

$ program >&- 2>&-
2

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

strace -p $pid 2>&1 | less
1

2: Это для случаев, когда у вас будут выходные данные как из стандартной ошибки, так и из стандартной ошибки, и вы хотите, чтобы они были объединены в одну строку.

1: когда вы хотите манипулировать выводом как стандартной ошибки, так и стандартной ошибки.

0

Случай перенаправления stderr в stdout уже был рассмотрен здесь (например, используйте его для фильтрации (grep) сообщений об ошибках).

Другой случай - перенаправление stdout в stderr. Обычный вариант использования (по крайней мере для меня) - отправлять предупреждения / сообщения об ошибках, напечатанные с помощью "echo" (в моих скриптах) в stderr (чтобы они могли легче привлечь внимание пользователя).

Например,

echo "file \"${file\" does not exist..." 1>&2
0

Альтернативный сценарий: команды терминала показывают вывод в другой терминал

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

$ tty
/dev/pts/0

$ tty
/dev/pts/1

Предполагая, что эти TTY, чтобы перенаправить стандартный вывод первого на второй, запустите это в первом терминале:

exec 1>/dev/pts/1

Примечание: теперь каждый вывод команды будет отображаться в pts/1

Чтобы восстановить стандартное поведение pts/0:

exec 1>/dev/pts/0

Смотрите это видео для демонстрации.

0

Я использую это, чтобы начать отдельную работу:

someProgram 2>&1 >& my.log &

тогда я могу выйти из системы, и некоторые программы все еще будут работать. Функциональность обеспечивается GNU Screen, tmux и некоторыми другими программами, но здесь это достигается без каких-либо внешних зависимостей.

0

Представьте, что есть каталог с именем try котором есть три файла: file file1 and file2.

Теперь запустите эту команду:

cat file file1 file2 file3

Первые три файла открываются, но cat выдает ошибку при открытии четвертого, так как он не существует.

Теперь запустите:

cat file file1 file2 file3 1>outfile 2>&1

Вы не увидите никаких выводов на экране: сначала 1>outfile перенаправит вывод команды в outfile а затем перенаправит (2>&1) ошибку, возникшую при попытке открыть file3 в outfile .

1>&2 работает аналогично и перенаправляет поток ошибок на стандартный вывод.

Надеюсь это поможет!

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .