将命令的 stdout 和 stderr 都记录到日志文件中相当简单:
./foo.sh &> log.txt
问题是在检查日志文件时,人们不再知道哪一行来自哪个流。这可以通过将 stdout 和 stderr 重定向到两个单独的文件来解决,但是输出的年表和交错会丢失。
另一种解决方案是重定向到三个文件。一种与标准输出,一种与标准错误,一种与两者结合。就像是:
./foo.sh 2> >(tee stderr | tee -a combined) 1> >(tee stdout | tee -a combined)
但是拥有这么多文件并不是很优雅(而且这个命令仍然会在 shell 上转储输出的副本)。
我发现了一个有趣的 bash 函数,它只会将 stderr 消息着色为红色:
color()(set -o pipefail;"$@" 2>&1>&3|sed $'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