Suppose I have a program foo
which prints to both stderr and stdout. I want to be able to time it and tee
the output to a log file.
I can call foo
as follows:
user$ time ./foo
This gives (for example) output on two streams:
stdout:
stdout says hi
stderr:
stderr says hi
I can combine them easily enough to standard output using BASH I/O redirection:
user$ ./foo 2>&1
This gives the following output:
stdout:
stdout says hi
stderr says hi
stderr: (empty!)
tee
I can capture the combined output of the program using tee
:
user$ ./foo 2>&1 | tee log.txt
stdout:
stdout says hi
stderr says hi
stderr: (empty!)
log.txt:
stdout says hi
stderr says hi
time
I can time the execution of my program using BASH's builtin time
command while combining stdout and stderr:
user$ time ./foo 2>&1
stdout:
stdout says hi
stderr says hi
stderr::
real 0m0.017s
user 0m0.003s
sys 0m0.004s
I can capture the output of the time
command as described here and redirect it to a file:
user$ ( time ./foo ) > log.txt
stdout: (empty!)
stderr:
stderr says hi
real 0m0.017s
user 0m0.003s
sys 0m0.004s
log.txt: stdout says hi
time
's output, AND piping to tee
How can this be done? I'm imagining something like the following:
( time ./foo 2&>1 ) | tee log.txt
stdout: (empty!)
stdout says hi
stderr says hi
real 0m0.017s
user 0m0.003s
sys 0m0.004s
stderr: (empty!)
log.txt:
stdout says hi
stderr says hi
real 0m0.017s
user 0m0.003s
sys 0m0.004s
Doing the following works, except when I Ctrl-C (SIGINT) out of the program prematurely.
( time ./foo ) 2&>1 | tee log.txt
How can I get it to work when I Ctrl-C as well?
myfunc() { echo stdout; echo stderr >&2; sleep 3; }
{ time myfunc; } > >(tee log.txt) 2>&1
...emits content including time
metadata to log.txt
, even when cancelled with Ctrl+C.
See Write tcpdump output to compressed / gziped file for a more-in-depth discussion of the same problem, including an answer intended for scripts as opposed to interactive interpreters.
For the program foo
in your example, you could do the following:
{ time ./foo; } > >(tee log.txt) 2>&1