Різниця між 2> & 1> output.log та 2> & 1 | tee вихід.log


35

Я хотів знати різницю між наступними двома командами

2>&1 > output.log 

і

2>&1 | tee output.log

Я бачив, як один з моїх колег використовував другий варіант для переадресації. Я знаю, що робить 2> і 1, моє єдине питання - яка мета використання трійника, де може бути використаний простий перенаправлення ">" оператора?

Відповіді:


11

Дивлячись на дві команди окремо:

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 спрямований на tee, так само 2. Оскільки tee дублює потік, вихід відображається як на консолі, так і записується у файл? Отже, різниця між 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
Kusalananda

Спасибі. Ви маєте на увазі це через те, що команда utility > output.log | more_stuffне призводить до виведення в стандартний вихідний потік зі стандартної точки зору помилки?
Мотивовано

@ Мотивовано Оскільки ліва частина нічого не створює на стандартному виході (він переспрямований), дані по каналу не надсилатимуться.
Kusalananda

24

Примітка редакції

Будь ласка, обов'язково прочитайте коментарі до цієї відповіді - дероберт .


Оригінальна відповідь

2>&1 >output.logозначає, спочатку почніть надсилати всі файли з обробкою файлів 2 (стандартна помилка) до файлу 1 (стандартний вихід), а потім надіслати його у файл output.log. Іншими словами, надішліть стандартний помилку та стандартний вихід у файл журналу.

2>&1 | tee output.logте ж саме з 2>&1бітом, він поєднує стандартний вихід і стандартну помилку на стандартний вихідний потік. Потім teeвін передає програму, яка надсилатиме стандартний вхід на його стандартний вихід (наприклад cat), а також у файл. Таким чином, він об'єднує два потоки (помилка та вихід), потім виводить цей термінал і файл.

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

Я згадую про останню можливість, тому що ви можете мати такі речі, як:

(echo hello | tee xyzzy.txt) >plugh.txt

де нічого не закінчується на терміналі.


13
-1 Ви маєте правильний синтаксис, але не семантику. Запустити cat /doesnotexist 2>&1 >output.txt- ви побачите, що cat: /doesnotexist: No such file or directoryвідображається на терміналі, а output.txt - порожній файл. Порядок пріоритетності та закриття є у грі: 2>&1(dup fd2 від поточного fd1), потім >output.txt(перенаправлення fd1 на output.txt, нічого іншого не змінюючи). Причина 2>&1 |в іншому полягає в порядку пріоритетності: |раніше >.
Арседж

5
Ця відповідь принципово неправильна по суті в усіх відношеннях . Багато відповідей нижче є кращими, але я вважаю, що ця Кусалаланда є найяснішою .
Майкл Гомер

2
@ user14408: Якщо ви хочете коли-небудь зробити акаунт на Unix & Linux і вимагати цю відповідь, будь ласка, видаліть мою редакційну записку, як тільки ви звернетесь до коментарів.
дероберт

8

Перша команда зробить інше завдання:

Після

2>&1 > output.log 

стара STDOUT буде збережена (скопійована) у STDERR, а потім STDOUT буде переспрямована у файл.

Отже, stdout перейде у файл, а stderr - у консоль.

І в

 2>&1 | tee output.log

обидва потоки будуть перенаправлені на tee. Трійник буде дублювати будь-який вхід до свого stdout (консолі у вашому випадку) та до файлу ( output.log).

І є ще одна форма першої:

    > output.log  2>&1

це перенаправить і STDOUT, і STDERR у файл.


4

Колишні виходи лише у файл. Другий виводить як у файл, так і на екран.


4

Причина 2>&1 | teeполягає в тому, щоб мати можливість захоплювати як stdout, так і stderr в файл журналу і одночасно бачити його на екрані. Це також можна зробити >output.txt 2>&1 & tail -f, але ви не знаєте, коли закінчується фонова команда - закінчується програма чи працює без виводу. Це 2>&1 | teeбула загальна ідіома для програмістів.


Ви хочете сказати, що 2> & 1> file.txt, наприклад, не буде захоплювати як stdout, так і stderr до file.txt?
Мотивовано

0

Давайте спочатку подивимось зразок коду:

#include <stdio.h>
main() 
{
// message 1, on stdout (using  printf)
printf("%s",          "message 1, on stdout (using  printf)\n");

// message 2, on stdout (using fprintf)
fprintf(stdout, "%s", "message 2, on stdout (using fprintf)\n");

// message 3, on stderr (using fprintf)
fprintf(stderr, "%s", "message 3, on stderr (using fprintf)\n");
}

Дозволяє порівняти результати:
./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) повідомлення у файлі були надруковані на консолі


-1

Ось публікація, що підсумовує вихідні потоки Unix: http://www.devcodenote.com/2015/04/unix-output-streams.html

Фрагмент від публікації:

Є 3 стандартних вихідних потоку:

STDIN - Standard Input - Writes from an input device to the program
STDOUT - Standard Output - Writes program output to screen unless specified otherwise.
STDERR - Standard Error Output - Writes error messages. Also printed to the screen unless specified otherwise.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.