bash: redirect stderr to file and stdout + stderr to screen
With a recent bash, you can use process substitution.
foo 2> >(tee stderr.txt)
This just sends stderr to a program running tee.
More portably
exec 3>&1
foo 2>&1 >&3 | tee stderr.txt
This makes file descriptor 3 be a copy of the current stdout (i.e. the screen), then sets up the pipe and runs foo 2>&1 >&3
. This sends the stderr of foo to the same place as the current stdout, which is the pipe, then sends the stdout to fd 3, the original output. The pipe feeds the original stderr of foo to tee, which saves it in a file and sends it to the screen.
Related videos on Youtube
linuxguy
Updated on September 18, 2022Comments
-
linuxguy over 1 year
I would like to save the stderr stream of a command into a log file but I also want to display the whole output (stdout + stderr) on the screen. How can I do this?
I only found the solution to display stdout + stderr to the console and redirect both streams to a file as well:
foo | tee output.file
(https://stackoverflow.com/questions/418896/how-to-redirect-output-to-a-file-and-stdout)
But I only want to redirect stderr to the log file.
-
Admin over 7 yearsThis might be helpful stackoverflow.com/questions/692000/…
-
-
linuxguy over 7 yearsGreat, that solve my issue!
-
Master DJon over 6 years
foo 2>&1 >&3 | tee stderr.txt
is working as intended, but I would like to have both to a file and errors to an another. I tried multiple things but nothing do it. Do you have any suggestions? This way, it is easier to locate errors with the real execution by finding them in "both-file" from "error-file". -
Master DJon over 6 yearsI found my answer: stackoverflow.com/a/45426547/214898
-
x0a over 5 yearsIt works but I'm having trouble understanding how this doesn't cause recursion. 3 is redirected to stdout. But then stdout is redirected to &3?
-
icarus over 5 years@x0a Let me try and explain. The important thing to understand is the way the
foo 2>&1 >&3 | tee stderr.txt
is executed. The first thing that is handled is the|
. To handle this the shell creates a pipe, and then forks to create 2 processes. One handles thefoo 2>&1 >&3
and the other handles thetee stderr.txt
. The first connects stdout to the pipe, and the second connects stdin to the pipe. .... -
icarus over 5 years@x0a .... The first shell now does the redirections, left to right. So
2>&1
connects the stderr of what will be foo to the current stdout, i.e. the pipe, then>&1
redirects the stdout of what will become foo )which is currently pointing to the pipe) to the original stdout that was saved in 3 -
x0a over 5 years@icarus Ahh I see it now. So invoking the pipe replaces the original
&1
with a reference to tee's stdin. And so we don't lose access to the original&1
/stdout, we declare a "global" reference to it before we create the pipe (and call it&3
). Awesome, thanks! -
aviro over 2 yearsThis works as long as your shell is originally yours, and you haven't performed
su
command on the way to get the shell. Aftersu
, the/dev/stderr
(or out) is link to the tty that belongs to the original user, so the shell won't be able to open the file for writing.