Навіщо перенаправляти вихід на 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.