С bash, как я могу передать стандартную ошибку в другой процесс? - PullRequest
117 голосов
/ 02 октября 2009

Хорошо известно, как передать стандартный вывод процесса в стандартный ввод другого процесса:

proc1 | proc2

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

proc1 2| proc2

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

Ответы [ 5 ]

142 голосов
/ 27 марта 2012

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

process1 2> file

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

process1 2> >(process2)

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

sh myscript 2> >(tee -a errlog)
86 голосов
/ 02 октября 2009

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

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

Если stdout и stderr оба указывают на одно и то же место в начале, это даст вам то, что вам нужно.

Бит x>y изменяет дескриптор файла x, поэтому теперь он отправляет информацию туда, куда указывает дескриптор файла y. Для нашего конкретного случая:

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

Это фактически команда подкачки, которую вы видите в алгоритмах сортировки:

temp   = value1;
value1 = value2;
value2 = temp;
64 голосов
/ 02 октября 2009

Bash 4 имеет эту функцию:

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

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

-

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

FirstCommand 2> & 1 | OtherCommand

26 голосов
/ 16 декабря 2011

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

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

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

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

Как это перенаправит все на /dev/null!

0 голосов
/ 01 февраля 2019

Ни один из них действительно не работал очень хорошо. Лучший способ сделать то, что вы хотели, это:

(command < input > output) 2>&1 | less

Это работает только в тех случаях, когда command не требует ввода с клавиатуры. например:

(gzip -d < file.gz > file) 2>&1 | less

поместит ошибки gzip в меньшее

...