Питання У оболонці, що означає "2> & 1"?


У оболонці Unix, якщо я хочу об'єднати stderr і stdout в stdout Потік для подальшого маніпулювання, я можу додати наступне в кінці моєї команди:

2>&1

Отже, якщо я хочу використовувати head на виході з g++, Я можу зробити щось на зразок цього:

g++ lots_of_errors 2>&1 | head

так що я бачу лише перші кілька помилок.

У мене завжди є проблеми із запам'ятовуванням цього, і я постійно повинен йти шукати, і це головним чином тому, що я не повністю розумію синтаксис цього конкретного трюку.

Чи може хто-небудь зламати це і пояснити характер по характеру що 2>&1  засоби?


1737
2018-05-03 22:57


походження


@ dbr Я не думаю, що це просто бас - я вважаю, що це боронна оболонка; отже sh, bash, ksh, ash, dash і т. д. - guns
Це частина абзацу перенаправлення, що описує POSIX-сумісні оболонки, або оболонку POSIX для коротких. ksh - це оболонка POSIX, наприклад. Побачити:pubs.opengroup.org/onlinepubs/009695399/utilities/... - jim mcnamara
Ця конструкція також працює на Windows. - Vadzim
Як правило, краще робити 2>&1 ніж 2> / dev / null ;-) - F. Hauri
Я думав, що згадую це |&  це скорочення для 2>&1 | якщо ви використовуєте zsh Я не можу говорити, чи застосовується це до інших бурн-подібних оболонок, або якщо це лише функція zsh. - chrixian


Відповіді:


Дескриптор файлу 1 є стандартним виходом (stdout)
Дескриптор файлу 2 є стандартною помилкою (stderr)

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


1943
2018-05-03 23:04



але тоді не варто це бути &2>&1? - dokaspar
@ Домінік: Ні, & трактується лише як "дескриптор файлу" в контексті переспрямувань. Написання command &2>& розбирається як command & і 2>&1, тобто "запустіть" command у фоновому режимі, а потім запустіть команду 2 і перенаправити його в стандартний стандарт ". - Adam Rosenfield
Цікава інформація тут: mywiki.wooledge.org/BashFAQ/055 - Halil Özgür
Але як би ви перенаправляли stderr в файл з назвою "& 1"? - Martín Fixman
@Мартін: 2>'&1' - rogual


echo test > afile.txt

перенаправляє stdout до afile.txt. Це те ж саме, що робити

echo test 1> afile.txt

Щоб перенаправити stderr, ви робите:

echo test 2> afile.txt

>& це синтаксис перенаправлення потоку до іншого дескриптора файлу - 0 - stdin, 1 - stdout і 2 - stderr.

Ви можете переадресовувати stdout на stderr шляхом виконання:

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

Або навпаки:

echo test 2>&1

Так, коротше ... 2> перенаправляє stderr до (неуточненого) файлу, додаючи &1 переспрямує stderr до stdout.


481
2018-05-03 22:59



чи це має сенс для вас java ... 2&1 >> data.log, Я побачив, що один з моїх колег зробив це? - Thang Pham
@ Гаррі, який виглядає як оболонка, яка не є баш, або помилка .. cmd 2>&1 >> somefile.log додасть stdout / stderr до файла - це в основному те ж саме, що і вище, з >> file додати - dbr
@ dbr cmd 2>&1 >>file не переспрямовує stderr на файл, але cmd >> file 2>&1 робить Замовлення має значення. У першому випадку stderr перенаправляється до stdout оболонки (можливо, tty, якщо команда введена інтерактивно), а потім stdout спрямовується в файл. У другому випадку, stdout спрямовується в файл, а потім stderr спрямовується в одне і те ж місце. - William Pursell
Мені подобається відповідь вище, але це може бути дотик чіткіше. "2> & 1" перенаправляє stderr до мети stdout. Отже, якщо у вас є щось на кшталт "ls -l >> directoryContents 2> & 1" Результатом буде файл, який називається directoryContents, буде додано вміст робочого каталогу. Якщо є будь-які помилки при виконанні: повідомлення про помилку також будуть додані до файлу directoryContents, оскільки вони виникають. - Max West
Є 0(or 1,2)>&0(or 1,2) як варіант керування виходом? Є echo test >test.log 2>&1 такий же, як echo test 2>&1 >test.log? - Simin Jie


Деякі трюки про перенаправлення

Деяка синтаксична особливість про це може мати важливу поведінку. Існує кілька невеликих зразків про перенаправлення STDERR, STDOUT, і аргументи замовлення.

1 - Перезапис або додавання?

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

  • > означає відправити в цілому завершений файл, перезаписати ціль, якщо є (див noclobber Функція Bash на №3 пізніше)
  • >> означає відправити на додаток до додасть до цілі, якщо є.

У будь-якому випадку цей файл буде створено, якщо він не існує.

2 - The командний рядок оболонки це замовлення залежне !!

Для цього ми потребуємо тестування проста команда, яка буде надсилати що-небудь на обох виходах:

$ 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

Нота: &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 опція і >| синтаксис

Ось про це перезапису:

Поки 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

Зняття цієї опції та / або запит, якщо це вже встановлено.

$ 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

4 - Останній трюк і багато іншого ...

Для переадресації обидва Вихід з даної команди ми бачимо, що правильний синтаксис може бути:

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

для цього особливий У випадку, є синтаксис ярликів: &> ... або >&

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

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

Нота: якщо 2>&1 існувати 1>&2 це також правильний синтаксис:

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

4b- Тепер я дам тобі подумати:

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

4c- Якщо вас цікавить більше інформація

Ви можете прочитати чудовий посібник, натискаючи:

man -Len -Pless\ +/^REDIRECTION bash

в  консоль ;-)


257
2018-04-29 16:33



Подальше читання: Якщо вам це сподобалось, ви можете спробувати: Як зловживання перенаправленням може призвести до незрозумілої поведінки - F. Hauri
Подальше читання ||: A функція для зберігання обох виходів на окремі змінні - F. Hauri


Цифри відносяться до дескрипторів файлів (fd).

  • Нуль є stdin 
  • Один є stdout 
  • Два є stderr

2>&1 перенаправлення від 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, які використовують нестандартні дескриптори файлів для користувацької реєстрації, тому ви не бачите його, якщо ви не перенаправляєте його в файл чи щось інше.


67
2018-05-03 22:58





Ця конструкція надсилає стандартний потік помилок (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 коли був виявлений аргумент (outfile1) та потім перенаправлення stdout до outfile2.

Це дозволяє дещо витончену обману.


49
2018-05-03 23:54



Хоча цей останній приклад буде набагато чіткішим: foo> outfile2 2> outfile1 - Michael Cramer
Яскравіше, так, але це не відображатиме "позиційний" характер перенаправлення. Приклад вигаданий, оскільки зазвичай це не є корисним в одному рядку - метод стає дійсно корисним, якщо різні сторони перенаправлення відповідають за різні сторони. Наприклад, коли скрипт робить один біт перенаправлення, і ви запускаєте його з іншим бітком. - paxdiablo
Я тільки що зрозумів, що останній приклад також вирішує довготривалу плутанину, яку я мав щодо чого: some_program 2>&1 > /dev/null не працює так: some_program > /dev/null 2>&1. - snapfractalpop
Ваш коментар щодо останнього прикладу вартий своїх листів золотом :-) Я ніколи не думав, що ці перенаправлені аргументи є позиційними ... Я думаю, це дуже важливо знати. - Nils-o-mat


Я знайшов цей блискучий пост за переспрямуванням: Все про перенаправлення

Перенаправляти як стандартний вихідний, так і стандартний помилки в файл

$ command &> файл

Цей один-лайнер використовує &> Оператор перенаправляє обидва вихідні потоки - stdout і stderr - від команди до файлу. Це ярлик Bash для швидкого перенаправлення обидва потоки на той самий пункт призначення.

Ось як виглядає таблиця дескрипторів файлів після того, як Bash переспрямовує обидва потоки:

Enter image description here

Як ви бачите, тепер і stdout, і stderr вказують file. Так що щось написане на stdout і stderr написано file.

Існує кілька способів перенаправлення обох потоків до одного місця призначення. Ви можете перенаправити кожен потік один за іншим:

$ command> файл 2> & 1

Це набагато більш поширений спосіб перенаправлення обох потоків у файл. Перший stdout перенаправляється до файла, а потім stderr дублюється, щоб бути таким же, як stdout. Обидва потоки в кінцевому підсумку вказують на file.

Коли Баш бачить кілька переспрямувань, він обробляє їх зліва направо. Давайте пройдемо кроки і подивимося, як це відбувається. Перш ніж запускати будь-які команди, таблиця дескрипторів файлу Bash виглядає так:

Enter image description here

Тепер Bash обробляє перший перенаправлення> файл. Ми бачили це раніше, і це робить stdout точкою до файлу:

Enter image description here

Наступний Bash бачить друге перенаправлення 2> & 1. Ми не бачили цього переспрямування раніше. Це один дублікат дескриптора 2 файлу, який є копією дескриптора файлу 1, і ми отримуємо:

Enter image description here

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

Але будьте обережні тут! Написання

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

не так, як писати:

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

Порядок перенаправлень має значення в Bash! Ця команда переспрямовує лише стандартний вихідний файл. Стандарт все одно надрукує на термінал. Щоб зрозуміти, чому це трапляється, давайте повторимо кроки. Тому перед запуском команди таблиця дескрипторів файлу виглядає так:

Enter image description here

Тепер Bash обробляє переспрямування зліва направо. Спочатку він бачить 2> & 1, тому він дублює stderr до stdout. Дескриптор таблиці стає таким:

Enter image description here

Тепер Баш бачить другу перенаправлення >file, і він переспрямовує stdout на файл:

Enter image description here

Ви бачите, що тут відбувається? Stdout тепер вказує на файл, але stderr все ще вказує на термінал! Все, що написано на stderr, все ще надруковується на екрані! Тож будьте дуже, дуже обережні з наказом переспрямувань!

Також зауважте, що в Баш, пише

$ command &> файл

точно так само, як:

$ command> & файл


47
2017-10-29 13:04



Останні два є різними, якщо "команда" закінчується числом, як тоді, що приймається як необов'язковий дескриптор файлу для >& - M.M
чудове пояснення! Дякую - Vicer


2>&1 це конфігурація оболонки POSIX. Ось розбивка, токен за токеном:


2: "Стандартна помилка"дескриптор вихідного файлу.

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

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

Вираз 2>&1 копіює дескриптор файлу 1 до місця розташування 2, тому будь-який вихідний текст записується 2 ("стандартна помилка") в середовищі виконання виходить у той самий файл, який спочатку описано 1 ("стандартний вихід").


Подальше пояснення:

Дескриптор файлу: "Універсальне невід'ємне ціле число, яке використовується для ідентифікації відкритого файлу з метою доступу до файлу".

Стандартний висновок / помилка: Зверніться до наступної примітки в Перенаправлення розділ документації оболонки:

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


13
2017-12-25 06:43





Щоб відповісти на ваше запитання: він приймає будь-який вивід помилки (зазвичай надсилається на stderr) і записує його на стандартний вивід (stdout).

Це корисно, наприклад, "більше", коли вам потрібне підключення до виводу. Деякі програми, такі як інформація про використання друку в stderr.

Щоб допомогти вам запам'ятати

  • 1 = стандартний вихід (де програми друкують нормальний вихід)
  • 2 = стандартна помилка (де виникають помилки друку програм)

"2> & 1" просто вказує на все, що відправлено до stderr, замість stdout.

Я також рекомендую читати цей пост при переспрямуванні помилок де цей предмет повністю висвітлений.


12
2018-05-03 23:24





2 - стандартна помилка консолі.

1 - стандартний вихід консолі.

Це стандартний Unix, і Windows також слідувати POSIX.

Наприклад, коли ти біжиш

perl test.pl 2>&1

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

perl test.pl > debug.log 2>&1

Після виконання, ви можете побачити весь вихід, включаючи помилки, в debug.log.

perl test.pl 1>out.log 2>err.log

Потім стандартний вихід виходить на out.log, а стандартна помилка - err.log.

Я пропоную вам спробувати зрозуміти це.


12
2017-07-19 03:23



Другий зразок неправильний: як пріоритет порядку STDERR переспрямовується на STDOUT, тільки за замовчуванням STDOUT буде написано debug.log (ні STDERR) побачити моя відповідь (абзац № 2)! Гарантувати обидва Щоб бути перенаправленим до того ж файлу, потрібно інвертувати директиви перенаправлень: perl test.pl > debug.log 2>&1 - F. Hauri


З погляду програміста це означає саме це:

dup2(1, 2);

Див людина сторінка.

Розуміння цього 2>&1 це скопіювати також пояснює, чому ...

command >file 2>&1

... це не те саме, що ...

command 2>&1 >file

Перший надсилає обидва потоки file, тоді як другий відправить помилки до stdout, і звичайний вихід у file.


10
2017-12-03 10:20