How can I save stdout to one file, stderr to another file, stdout+stderr to a third file and also get stdout + stderr to terminal like normal for a shell script?
I found this elsewhere:
exec > >(tee std_out) 2> >(tee err_out >&2)
ls # Should got to std_out
fsdfs # Command not found goes to err_out
Which is really close. If I run bash test.sh 2>&1 | tee output
then it works, but I don't have access to how my script is run. It's a cicd system. I need to be able to do the "combined output" from inside the script using exec.
I'm creating a CI/CD library and I'm unable to know what the clients would use the library for, so I want to account for each use case.
Best Answer
Simply expanding on your approach:
Standard error will be written to the file named
stderr
, standard output tostdout
and both standard error and standard output will also be written to the console (or whatever the two file descriptors are pointing at the timeexec
is run) and tostdall
.tee -a
(append) is required to preventstdall
from being overwritten by the secondtee
that starts writing to it.Note that the order in which redirections are performed is relevant: the second process substitution is affected by the first redirection, i.e. the errors it emitted would be sent to
>(tee -a stderr stdall)
. You can, of course, redirect the second process substitution's standard error to/dev/null
to avoid this side effect. Redirecting standard output before standard error would send every error tostdout
andstdall
too.Since the commands in Bash's process substitutions are executed asynchronously, there is no way to guarantee that their output will be displayed in the order it was generated. Worse, fragments from standard output and standard error are likely to end up appearing on the same line.