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