### do this bit once at the top of your script
divert=
exec 3<>"${divert:=$(mktmp)}" 4<>/dev/null
rm -- "$divert"; unset divert
### then do this bit as often as needed
command >&3 2>&3
cat <&3 >&"$(((RTN=$?)?2:4))"
Это, вероятно, должно сработать. Он буферизует вывод каждого из них command
в удаленный временный файл, а затем откачивает свой вывод в любой из них /dev/null
или в stderr в зависимости от того, был ли его статус возврата не нулевым. Поскольку временный файл удаляется досрочно, он не может быть прочитан каким-либо процессом, кроме текущей оболочки и ее дочерних элементов в дескрипторе файла (за исключением скрытого /proc/$pid/fd
отслеживания с соответствующими разрешениями) , и он не требует очистки по окончании.
Возможно, более удобное решение для систем Linux:
divert(){
"$@" >&3 2>&3 ||
eval "cat <&3
return $?"
} 3<<"" 3<>/dev/fd/3
... которые, в большинстве оболочек, так же, как другие работают, за исключение того, что вы можете назвать это как: divert some simple-command with args
. Остерегайтесь высокопроизводительных команд в "$@"
, хотя для dash
, yash
или в некоторых других оболочках, которые делают здесь - документы с каналами - я думаю, что в этих оболочках может быть возможно заполнить буфер канала (по умолчанию около 128 КБ в linux) и таким образом тупик , Это не должно быть беспокойства для ksh
, mksh
, bash
, zsh
, или Bourne оболочки, хотя - все те делают в основном то же самое, что я явно выше exec
.