Навіщо перенаправляти вихід на 2> & 1 і 1> & 2?


36

Я натрапив на декілька команд, які використовують 2>&1і 1>&2, але я не можу обернути головою цілі його використання і коли мені слід його використовувати.

Що я розумію

Я знаю, що 1являє собою стандартний вихід і 2представляє стандартну помилку. Я розумію , що 2>&1комбінати вихід 2до 1і навпаки.

Чого я не отримую

  1. Коли я повинен використовувати його?
  2. Якій цілі він служить?

Відповіді:


39

Іноді ви хочете перенаправити як 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) вже вказує на потрібне місце, але ви не можете посилатися на нього по імені (це може бути пов'язано з трубою, сокетом чи іншим). Це часто трапляється при використанні розширення процесів ( ` `або $( )операторів), яке, як правило, лише фіксує stdout, але ви можете включити в нього stderr. У цьому випадку ви також використовуєте, >&щоб вказати stderr на stdout:

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до >&fooабо&>foo

  • 2>&1 | program до |& program


Я не мав уявлення, що це app 1>/dev/null 2>&1означатиме, що 2> і 1 вказуватимуть на файл, до якого 1 вже перенаправлено. Я вважаю, що міг би так само легко зробити app > /dev/null &>?
— АрахісМонкі

Мені важко зрозуміти the already set up fd goes to the right of >&, and the fd you want to redirect goes to the left. Що ви маєте на увазі під уже створеним дескриптором файлів? Що означає право?
— PeanutsMonkey


Вибачте, якщо ви не мали наміру навчити мене вказівкам, я не дотримуюся заяви, яку ви зробили, як було зазначено раніше.
— PeanutsMonkey

1
Візьміть кожен дескриптор файлів, переспрямовуючи їх по черзі, зліва направо і застосуйте ці правила в тому порядку. Якщо ви спочатку направляєте stdout у файл, потім перенаправляєте stderr туди, куди зараз вказує нам stdout, тоді stderr та stdout перейдуть до того ж файлу. Якщо поміняти місцями ці два переадресовує навколо, то ви отримаєте різні результати (Перенаправлення STDERR, де стандартний висновок буде в даний час , а потім перейти до STDOUT точку в інший файл, в той час як STDERR триває , де це було зазначено в).
— Джейсон

2

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

strace -p $pid 2>&1 | less

Що ви маєте на увазі під pipes generally connect standard output to standard input?
— PeanutsMonkey

2
Я маю на увазі, що pipe ( |) приймають стандартний вихід першої команди і підключають його до стандартного входу другої команди.
— jpalecek

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>&-

1

2: Це коли ви отримаєте вихід із стандартної помилки та стандартної помилки, і ви хочете, щоб вони складалися в одну рядок.

1: Коли ви хочете маніпулювати висновком як стандартної помилки, так і стандартної.


Що ви маєте на увазі під маніпулюванням? Я розумію, що все, на що переспрямовано >2, надсилається в / dev / null. Або я зовсім помилився?
— PeanutsMonkey

Це не правильно. Під маніпулюванням я маю на увазі трубу в греп або щось подібне. Дивіться тут приклад.
— soandos

0

Я використовую його для початку окремої роботи:

someProgram 2>&1 >& my.log &

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


1
Це працює лише до тих пір, поки в програму не буде надісланий SIGHUP. Краще використовувати nohupабо disownв таких випадках.
— slhck

@slhck: добре. Але якщо я не надішлю SIGHUP до програми - ніхто не буде, правда?
— Adobe

Ні, контрольний термінал попередить процеси виходу з SIGHUP. На практиці, якщо ви запустите віддалену оболонку через SSH та вихід, наприклад, ваш процес загине.
— slhck

@slhck: Не може бути правдою: я використовую її кілька років - я виходжу з ssh, і процес все ще працює.
— Adobe

Мені доведеться розглянути це більш детально, але просто введення програм у фоновий режим для мене не працює в усіх випадках, і це точно не працює навіть на моїй локальній машині. Зш і Баш тут теж поводяться по-різному, схоже.
— slhck

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 працює аналогічно і перенаправляє потік помилок на стандартний вихід.

Сподіваюся, це допомагає!


0

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

Використовуйте ttyкоманду в кожному терміналі, щоб ідентифікувати їх:

$ tty
/dev/pts/0

$ tty
/dev/pts/1

Припускаючи ці TTY, щоб перенаправити stdout першого на другий, запустіть це у першому терміналі:

exec 1>/dev/pts/1

Примітка: Тепер кожен вихід команди відображатиметься на pts / 1

Щоб відновити типову поведінку за замовчуванням pts / 0:

exec 1>/dev/pts/0

Дивіться це відео для демонстрації.


0

Тут уже висвітлено випадок, коли перенаправлення stderr на stdout (наприклад, використовуйте його для фільтрації (grep) повідомлень про помилки).

Інший випадок - перенаправлення stdout на stderr. Поширена справа використання (принаймні для мене) - надсилання попереджень / повідомлень про помилки, надруковані "ехо" (у моїх оболонках) на stderr (щоб вони легше привернули увагу користувача).

Наприклад,

echo "file \"${file\" does not exist..." 1>&2
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.