如何使用包含 SIGINT 的 tee 捕获 stderr 和 stdout 以及计时信息?

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

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

计划说明

我可以调用 foo 如下:

user$ time ./foo

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

标准输出:

stdout says hi

标准错误:

stderr says hi

结合 stderr 和 stdout

我可以使用 BASH I/O 重定向很容易地将它们组合成标准输出:

user$ ./foo 2>&1

这给出了以下输出:

标准输出:

stdout says hi
stderr says hi

stderr:(空!)

使用tee

我可以使用 tee:

捕获程序的组合输出
user$ ./foo 2>&1 | tee log.txt

标准输出:

stdout says hi
stderr says hi

stderr:(空!)

log.txt:

stdout says hi
stderr says hi

使用 time

捕获时间

我可以使用 BASH 的内置 time 命令计时我的程序的执行时间 结合 stdout 和 stderr:

user$ time ./foo 2>&1

标准输出:

stdout says hi
stderr says hi

标准错误:

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

我可以按照 here 所述捕获 time 命令的输出并将其重定向到文件:

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

标准输出:(空!)

标准错误:

stderr says hi

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

log.txt: 标准输出说嗨

合并 I/O,捕获 time 的输出,并通过管道传输到 tee

如何做到这一点?我在想像下面这样的事情:

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

标准输出:(空!)

stdout says hi
stderr says hi

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

stderr:(空!)

log.txt:

stdout says hi
stderr says hi

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

做以下工作,除了当我 Ctrl-C (SIGINT) 过早退出程序时。

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

我怎样才能让它在我按 Ctrl-C 时也能正常工作?

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

...将内容 包括 time 元数据发送到 log.txt,即使使用 Ctrl+ 取消也是如此C.

请参阅 了解对同一问题的更深入讨论,包括针对脚本而不是交互式解释器的答案。


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

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