关于bash:如何使用包括SIGINT在内的tee捕获stderr和stdout以及时序信息?

How to capture stderr and stdout AND timing info with tee including SIGINT?

假设我有一个程序foo,它打印到stderr和stdout。我希望能够将它和tee输出计时到日志文件。

程序说明

我可以按如下方式调用foo

1
user$ time ./foo

这给出了(例如)两个流的输出:

标准输出:

1
stdout says hi

标准错误:

1
stderr says hi

结合stderr和stdout

我可以使用BASH I / O重定向轻松地将它们组合到标准输出:

1
user$ ./foo 2>&1

这给出了以下输出:

标准输出:

1
2
stdout says hi
stderr says hi

stderr :(空!)

使用tee

我可以使用tee捕获程序的组合输出:

1
user$ ./foo 2>&1 | tee log.txt

标准输出:

1
2
stdout says hi
stderr says hi

stderr :(空!)

log.txt的:

1
2
stdout says hi
stderr says hi

使用time捕获计时

在组合stdout和stderr时,我可以使用BASH的builtin time命令执行我的程序:

1
user$ time ./foo 2>&1

标准输出:

1
2
stdout says hi
stderr says hi

标准错误::

1
2
3
real    0m0.017s
user    0m0.003s
sys     0m0.004s

我可以捕获time命令的输出,如此处所述,并将其重定向到文件:

1
user$ ( time ./foo ) > log.txt

stdout :(空!)

标准错误:

1
2
3
4
5
stderr says hi

real    0m0.017s
user    0m0.003s
sys     0m0.004s

log.txt的:
stdout说嗨

组合I / O,捕获time的输出,并将管道连接到tee

如何才能做到这一点?我想象的东西如下:

1
( time ./foo 2&>1 ) | tee log.txt

stdout :(空!)

1
2
3
4
5
6
stdout says hi
stderr says hi

real    0m0.017s
user    0m0.003s
sys     0m0.004s

stderr :(空!)

log.txt的:

1
2
3
4
5
6
stdout says hi
stderr says hi

real    0m0.017s
user    0m0.003s
sys     0m0.004s

执行以下操作,除非我过早地按Ctrl-C(SIGINT)退出程序。

1
( time ./foo ) 2&>1 | tee log.txt

我怎么能在Ctrl-C时让它工作?


1
2
myfunc() { echo stdout; echo stderr >&2; sleep 3; }
{ time myfunc; } > >(tee log.txt) 2>&1

...即使用Ctrl + C取消,也会将包含time元数据的内容发送到log.txt

请参阅将tcpdump输出写入compressed / gziped文件,以便对同一问题进行更深入的讨论,包括针对脚本而不是交互式解释器的答案。

对于示例中的程序foo,您可以执行以下操作:

1
{ time ./foo; } > >(tee log.txt) 2>&1