Bash:记录stdout和stderr,同时保留订单和出处

时间:2013-07-16 18:55:07

标签: bash logging io-redirection

将stdout和stderr命令记录到日志文件中相当简单:

./foo.sh &> log.txt

问题在于,在检查日志文件时,人们不再知道哪一行来自哪个流。这可以通过将stdout和stderr重定向到两个单独的文件来修复,但随后输出的时间顺序和交错将丢失。

另一种解决方案是重定向到三个文件。一个是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

2 个答案:

答案 0 :(得分:2)

也许您正在寻找script 它记录stdout,stderr和命令......它启动一个新的shell,在其中记录所有内容(或使用-c _cmd_

 $ script tx1

您的color()函数因为sed正在缓冲...

而中断了订单

答案 1 :(得分:1)

如何将stderr重定向到./tmperr并将stdout重定向到./tmpout,现在在后台运行两个脚本,每个脚本从tmperr或tmpout连续读取一行,然后删除该行?这显然不太理想,但如果在实际的foo.sh脚本中有一个不错的延迟,这应该可以解决。