Глядя на две команды отдельно:
utility 2>&1 >output.log
Здесь, поскольку перенаправления обрабатываются слева направо, стандартный поток ошибок сначала перенаправляется туда, куда идет стандартный поток вывода (возможно, на консоль), а затем стандартный поток вывода перенаправляется в файл. Стандартный поток ошибок не будет перенаправлен в этот файл.
Видимый эффект этого состоит в том, что вы получаете то, что вырабатывается при стандартной ошибке на экране, и то, что вырабатывается при стандартном выводе в файл.
utility 2>&1 | tee output.log
Здесь вы перенаправляете стандартную ошибку в то же место, что и стандартный поток вывода. Это означает, что оба потока будут переданы в tee
утилиту как один смешанный выходной поток, и что эти стандартные выходные данные будут сохранены в данный файл tee
. Данные будут дополнительно воспроизводиться tee
в консоли (это то tee
, что делает, он дублирует потоки данных).
Какой из этих способов использовать, зависит от того, чего вы хотите достичь.
Обратите внимание, что вы не сможете воспроизвести эффект второго конвейера просто >
(как в случае utility >output.log 2>&1
, который сохранит как стандартный вывод, так и ошибку в файле). Вам нужно будет использовать tee
для получения данных в консоли, а также в выходной файл.
Дополнительные замечания:
Видимый эффект первой команды,
utility 2>&1 >output.log
будет так же, как
utility >output.log
Т.е. стандартный вывод идет в файл, а стандартная ошибка - в консоль.
Если в конце каждой из вышеперечисленных команд будет добавлен дальнейший этап обработки, будет большая разница:
utility 2>&1 >output.log | more_stuff
utility >output.log | more_stuff
В первом конвейере more_stuff
будет получено то, что изначально является стандартным потоком ошибок, в utility
качестве стандартных входных данных, тогда как во втором конвейере, поскольку это только результирующий стандартный поток вывода, который когда-либо отправляется через канал, more_stuff
часть конвейера ничего не получит. читать на своем стандартном входе.
utility 2>&1 | tee output.log
, вы хотите сказать, что поскольку 1 направлен на тройник, то 2 тоже. Поскольку тройник дублирует поток, выходные данные отображаются как на консоли, так и записываются в файл? Следовательно, разница междуutility 2>&1 > output.log
иutility 2>&1 | tee output.log
являетсяtee
тем , что он дублирует поток это будет правильно.?utility 2>&1 > output.log | more_stuff
иutility >ouput.log
| more_stuff, is the difference that
more_stuff` имеет стандартную ошибку вывода на консоль в качестве входаmore_stuff
? Поскольку во втором примере нет вывода на консоль, по сути, нет ввода вmore_stuff
? Если да, это не ясно, так как в предыдущем абзаце вы заметили, что стандартный вывод идет в файл, а стандартная ошибка - в консольmore_stuff
будет получено то, чтоutility
первоначально было отправлено в поток ошибок (но которое было перенаправлено на стандартный вывод). Не потому, что он оказался бы на консоли, если быmore_stuff
его там не было, а потому, что он идет в стандартный поток вывода . Во второй команде ничего неmore_stuff
получает, так как нет стандартного вывода с левой стороны конвейера. Поток ошибок из все равно попадет на консоль во 2-й команде.utility
utility > output.log | more_stuff
не приводит к выводу в стандартном потоке вывода с точки зрения стандартной ошибки?Редакционная заметка
Пожалуйста, не забудьте прочитать комментарии к этому ответу - Дероберт .
Оригинальный ответ
2>&1 >output.log
означает сначала начать отправку всего описателя файла 2 (стандартная ошибка) в описатель файла 1 (стандартный вывод), а затем отправить его в файлoutput.log
. Другими словами, отправьте стандартную ошибку и стандартный вывод в файл журнала.2>&1 | tee output.log
то же самое с2>&1
битом, он объединяет стандартный вывод и стандартную ошибку в стандартный поток вывода. Затем он передает это черезtee
программу, которая отправит свой стандартный ввод в стандартный вывод (напримерcat
), а также в файл. Таким образом, он объединяет два потока (ошибка и вывод), а затем выводит их на терминал и в файл.Суть в том, что первая отправляет
stderr
/stdout
в файл, а вторая отправляет его как в файл, так и в стандартный вывод (который, вероятно, является терминалом, если вы не находитесь внутри другой конструкции, которая перенаправляет стандартный вывод).Я упоминаю эту последнюю возможность, потому что вы можете иметь такие вещи, как:
где ничего не заканчивается на терминале.
источник
cat /doesnotexist 2>&1 >output.txt
- вы увидите см.cat: /doesnotexist: No such file or directory
Вывод на терминал и output.txt - пустой файл. Порядок приоритета и закрытия находятся в игре:2>&1
(дублируйте fd2 с текущего fd1), затем>output.txt
(перенаправьте fd1 в output.txt, не изменяя ничего больше). Причина, которая2>&1 |
отличается, из-за порядка приоритета:|
раньше>
.Первая команда выполнит другую задачу:
После
старый STDOUT будет сохранен (скопирован) в STDERR, а затем STDOUT будет перенаправлен в файл.
Итак, стандартный вывод перейдет в файл, а стандартный вывод в консоль.
И в
оба потока будут перенаправлены на тройник. Tee будет дублировать любой ввод в свой стандартный вывод (консоль в вашем случае) и в файл (
output.log
).И есть еще одна форма первого:
это перенаправит STDOUT и STDERR в файл.
источник
Первый выводит только в файл. Второй выводит как в файл, так и на экран.
источник
Причина
2>&1 | tee
заключается в том, чтобы иметь возможность записывать как stdout, так и stderr в файл журнала и одновременно видеть его на экране. Это также может быть сделано>output.txt 2>&1 & tail -f
, но вы не будете знать, когда прервана фоновая команда - завершена ли программа или она работает без вывода. Это2>&1 | tee
была общая идиома для программистов.источник
Давайте сначала посмотрим пример кода:
Давайте сравним результаты:
./helloerror
+ файл: нет сообщения; консоль: сообщение 1,2,3;
./helloerror >error.txt
+ файл: сообщение 1,2; консоль: сообщение 3;
./helloerror 2>&1 >error.txt
+ файл: сообщение 1,2; консоль: сообщение 3;
+ так же, как ./helloerror> error.txt
./helloerror >error.txt 2>&1
+ файл: сообщение 3,1,2; консоль: нет сообщения;
+ обратите внимание, что сначала идет порядок 3, затем 1, затем 2
./helloerror | tee error.txt 2>&1
+ файл: сообщение 1,2; консоль: сообщение 3,1,2;
+ обратите внимание, что сначала идет порядок 3, затем 1, затем 2
./helloerror 2>&1 | tee error.txt
+ файл: сообщение 3,1,2; консоль: сообщение 3,1,2;
Использовать: -> если нужно,
./helloerror >error.txt 2>&1
чтобы все (stdout + stderr) сообщения находились в файле, но не выводились на консоль
./helloerror 2>&1 | tee error.txt
-> если нужно, чтобы все (stdout + stderr) сообщения находились в файле и выводились на консоль
источник
Вот статья, в которой обобщены выходные потоки Unix: http://www.devcodenote.com/2015/04/unix-output-streams.html
Фрагмент из поста:
Есть 3 стандартных выходных потока:
источник