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

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

proc1 | proc2

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

proc1 2| proc2

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

Ответ 1

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

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

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

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

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

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

temp   = value1;
value1 = value2;
value2 = temp;

Ответ 2

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

process1 2> file

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

process1 2> >(process2)

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

sh myscript 2> >(tee -a errlog)

Ответ 3

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

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

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

-

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

FirstCommand 2 > & 1 | OtherCommand

Ответ 4

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

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

Порядок важен; вам не нужно:

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

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

Ответ 5

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

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

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

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

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