Что будет делать эта команда?
exec 2>&1
Что будет делать эта команда?
exec 2>&1
С технической точки зрения он дублирует или копирует stderr на stdout.
Обычно вам не нужен exec для выполнения этого. Более типичное использование exec с файловыми дескрипторами - указать, что вы хотите назначить файл неиспользуемому файловому дескриптору, например
exec 35< my_input
BTW Не забывайте, что последовательность объявлений, когда сообщение в файл важно, поэтому
ls > mydirlist 2>&1
будет работать, потому что он направляет как stdout, так и stderr в файл mydirlist, тогда как команда
ls 2>&1 > mydirlist
направляет только stdout, а не stderr, на файл mydirlist, потому что stderr был сделан копией stdout, прежде чем stdout был перенаправлен на mydirlist.
Изменить: Это способ сканирования оболочки слева направо. Поэтому прочитайте второй вариант, говоря "copy stderr на stdout", прежде чем он скажет: "Отправить stdout для mydirlist". Затем прочитайте первый, указав "отправьте stdout в файл mydirlist", прежде чем он произнесет "duplicate stderr на этот stdout, который я настроил". Я знаю. Это совершенно не интуитивно!
Одна из лучших статей, которые я видел по поводу того, что "2 > & 1" делает, Bash Объяснение одним слоем, часть III: все о перенаправлениях.
Но то, что текущие ответы на этот вопрос не дают, - это то, почему вы захотите сделать это после простого "exec". Поскольку справочная страница bash для команды exec объясняет: "Если команда не указана, любые перенаправления вступают в силу в текущей оболочке".
Я написал простой script вызываемый out-and-err.py, который записывает строку вывода в stdout, а другую строку - stderr:
#!/usr/bin/python
import sys
sys.stdout.write('this is stdout.\n')
sys.stderr.write('this is stderr.\n')
И затем я завернул, что в оболочке script вызывается out-and-err.sh с помощью "exec 2 > & 1":
#!/bin/bash
exec 2>&1
./out-and-err
Если я запускаю только python script, stdout и stderr являются отдельными:
$ ./out-and-err.pl 1> out 2> err
$ cat out
this is stdout.
$ cat err
the is stderr.
Но если я запустил оболочку script, вы увидите, что exec заботится о stderr для всего:
$ ./out-and-err.sh 1> out 2> err
$ cat out
this is stdout.
this is stderr.
$ cat err
$
Если ваша оболочечная оболочка script делает намного больше, чем только одна команда python, и вам нужен весь вывод, объединенный в stdout, выполнение "exec 2 > & 1" сделает это легко для вас.
Он связывает стандартную ошибку со стандартным
2
- stderr, а 1
- stdout. Когда вы запускаете программу, вы получите нормальный вывод в stdout, но любые ошибки или предупреждения обычно идут в stderr. Если вы хотите связать весь вывод с файлом, например, сначала скомпоновать stderr с stdout с помощью 2>&1
.
Как и @cma, он ставит stderr на stdout. Причина, по которой вам может понадобиться такое поведение, - использовать grep или любую другую утилиту для захвата вывода, который появляется только на stderr. Или вы можете просто сохранить весь вывод, включая stderr, в файл для последующей обработки.
Одним из весьма полезных приложений exec 2>&1
, с которыми я столкнулся, является то, что вы хотите объединить stderr
и stdout
для нескольких команд, разделенных точками с запятой. Мой конкретный пример произошел, когда я отправлял более чем одну команду в popen
в PHP, и мне хотелось, чтобы ошибки чередовали, как вы увидите, набрали ли вы команды в командной строке:
$ echo hi ; yikes ; echo there
hi
-bash: yikes: command not found
there
$
Следующее не объединяет stderr
и stdout
за исключением последнего echo
(что бессмысленно, потому что ошибка yikes
вызывает ошибку):
echo hi ; yikes ; echo there 2>&1
Я могу получить объединенный вывод "трудный путь" следующим образом:
echo hi 2>&1; yikes 2>&1; echo there 2>&1
Он выглядит намного чище и менее подвержен ошибкам, если вы используете exec
:
exec 2>&1 ; echo hi; echo yikes; echo there
Вы получаете выходные данные stdout
и stderr
, как показано на терминале, если вы выполнили три команды, разделенные точкой с запятой.