2009-10-02 2 views
93

Это хорошо известно, как труба стандартного потока вывода процесса на другую процессы стандарта ввод:С bash, как я могу передать стандартную ошибку в другой процесс?

proc1 | proc2 

Но что, если я хочу, чтобы отправить стандартную ошибку proc1 к proc2 и оставить стандартный вывод будет его ток место нахождения? Вы думаете, что bash бы команду по линиям:

proc1 2| proc2 

Но, увы, нет. Есть какой-либо способ сделать это?

+0

Вы можете сделать такое простое перенаправление в 'rc', которое является другой оболочкой. Например: 'proc1 | [2] proc2'. Разве это не приятно? Не в 'bash'. – Rolf

ответ

75

Вы можете использовать следующую информацию: свопstdout и stderr. Затем вы просто используете регулярные функции труб.

(proc1 3>&1 1>&2- 2>&3-) | proc2 

stdout Предоставлено и stderr и указал на то же место на старте, это даст вам то, что вам нужно.

Что он делает:

  • 3>&1 создает новый дескриптор файла 3, который установлен на текущий 1 (оригинальный стандартный вывод) просто сохранить его где-нибудь.
  • 1>&2- устанавливает stdout, чтобы получить текущий дескриптор файла 2 (оригинальный stderr), затем закрывается 2.
  • 2>&3- устанавливает stderr для доступа к текущему файловому дескриптору 3 (оригинал stdout), затем закрывается 3.

Это эффективно команда подкачки вы видите в сортировке:

temp = value1; 
value1 = value2; 
value2 = temp; 
+3

Каково значение использования '1> & 2-' здесь, а не только '1> & 2'? Я не понимаю, почему мы хотели бы закрыть fd '2', если мы просто собираемся снова открыть/переназначить его. – dubiousjim

+1

@dubiousjim, нет преимущества в этом конкретном случае, я подозреваю, что сделал это просто для того, чтобы быть последовательным - закрытие дескриптора файла 3 - хорошая идея, чтобы освободить его. – paxdiablo

+0

Вы, вероятно, забыли '&' в пояснениях о пуле. – ovgolovin

56

Bash 4 имеет эту особенность:

Если `| & ', стандартная ошибка команды 1 подключается к стандартному вводу команды через трубу; это сокращение для 2> & 1 |. Это неявное перенаправление стандартной ошибки выполняется после любых переназначений, указанных в команде.

zsh также имеет эту функцию.

-

С другими/старых оболочек, просто введите это в явном виде

FirstCommand 2> & 1 | OtherCommand

+11

Из-за чтения документов, которые выполняют как стандартную ошибку *, так и * вывод, а не только stderr, но это приятно знать. Полагаю, что время, чтобы начать смотреть на bash 4. – paxdiablo

+0

Текущее руководство bash гласит: «Если | & используется, стандартная ошибка команды **, в дополнение к ее стандартным выводам ** подключается к стандартным входам команды 2». Это явно не то, что хочет OP. –

+0

@ PeterA.Schneider: OP говорит: «Оставьте стандартный вывод в текущем местоположении», который может быть неоднозначным. –

18

Перестановка отличная, поскольку она решает проблему.Только в случае, если вы даже не нужен оригинальный стандартный вывод, вы можете сделать это следующим образом:

proc1 2>&1 1>/dev/null | proc2 

Порядок имеет жизненно важное значение; Вы не хотели бы:

proc1 >/dev/null 2>&1 | proc1 

Как это будет перенаправлять все, чтобы /dev/null!

108

Существует также process substitution. Это делает процесс заменой файла.
Вы можете отправить stderr в файл следующим образом:

process1 2> file 

Но вы можете заменить процесс для файла следующим образом:

process1 2> >(process2) 

Вот конкретный пример, который посылает stderr как к экрану и добавляется к файлу журнала

sh myscript 2> >(tee -a errlog) 
+14

Это правильно отвечает на поставленный вопрос и должен быть принятым ответом от @paxdiablo – mmlb

+0

Я пробовал это. Это не сработало ('weston --help 2>> (less)'), и он сломал мою оболочку, мне пришлось выйти и войти в систему. – Rolf