Bash: вход stdout и stderr при сохранении порядка и происхождения

Довольно просто записать как stdout, так и stderr команды в файл журнала:

./foo.sh &> log.txt

Проблема в том, что при проверке файла журнала больше не известно, какая строка поступает из какого потока. Это можно исправить, перенаправив stdout и stderr на два отдельных файла, но тогда хронология и чередование выходных данных будут потеряны.

Другим решением будет перенаправление на три файла. Один с stdout, один с stderr и один с обоими вместе взятыми. Что-то вроде:

./foo.sh 2> >(tee stderr | tee -a combined) 1> >(tee stdout | tee -a combined)

Но не так уж и элегантно иметь столько файлов (и эта команда по-прежнему выводит копию вывода в оболочку).

Я нашел интересную функцию bash, которая бы окрашивала только сообщения stderr в красный:

color()(set -o pipefail;"$@" 2>&1>&3|sed 

но он не сохраняет порядок вывода и результат не читается в текстовом редакторе. Учитывая следующую программу дляfoo.sh:

for i in 1 2; do
   for j in 1 2; do
     printf '%s\n' "out $i"
   done
   for k in 1 2; do
     printf '%s\n' "err $i" >&2
   done
done

Бегcolor ./foo.sh производит:

out 1
out 1
out 2
out 2
[31merr 1[m
[31merr 1[m
[31merr 2[m
[31merr 2[m

Как можно легко получить что-то подобное в одном файле журнала?

@| out 1
@| out 1
$| err 1
$| err 1
@| out 2
@| out 2
$| err 2
$| err 2
s,.*,\e[31m&\e[m,'>&2)3>&1

но он не сохраняет порядок вывода и результат не читается в текстовом редакторе. Учитывая следующую программу дляfoo.sh:

for i in 1 2; do
   for j in 1 2; do
     printf '%s\n' "out $i"
   done
   for k in 1 2; do
     printf '%s\n' "err $i" >&2
   done
done

Бегcolor ./foo.sh производит:

out 1
out 1
out 2
out 2
[31merr 1[m
[31merr 1[m
[31merr 2[m
[31merr 2[m

Как можно легко получить что-то подобное в одном файле журнала?

@| out 1
@| out 1
$| err 1
$| err 1
@| out 2
@| out 2
$| err 2
$| err 2

Ответы на вопрос(2)

Ваш ответ на вопрос