Bash - send all output to a log file, BUT show errors Bash - send all output to a log file, BUT show errors shell shell

Bash - send all output to a log file, BUT show errors


UNIX terminals usually provide two output file decriptors, stdout and stderr, both of which go to the terminal by default.

Well behaved programs send their "standard" output to stdout, and errors to stderr. So for example echo writes to stdout. grep writes matching lines to stdout, but if something goes wrong, for example a file can't be read, the error goes to stderr.

You can redirect these with > (for stdout) and 2> (for stderr). So:

 myscript >log 2>errors

Writes output to log and errors to errors.

So part of your requirement can be met simply with:

 command >log

... errors will continue to go to the terminal, via stdout.

Your extra requirement is "except the output i specifically output with echo".

It might be enough for you that your echos go to stderr:

 echo "Processing next part" >&2

The >&2 redirects stdout from this command to stderr. This is the standard way of outputting errors (and sometimes informational output) in shell scripts.

If you need more than this, you might want to do something more complicated with more file descriptors. Try: https://unix.stackexchange.com/questions/18899/when-would-you-use-an-additional-file-descriptor

Well behaved UNIX programs tend to avoid doing complicated things with extra file descriptors. The convention is to restrict yourself to stdout and stderr, with any further outputs being specified as filenames in the command line parameters.


Here is what you can do by using an additional file descriptor:

#!/bin/bash# open fd=3 redirecting to 1 (stdout)exec 3>&1# redirect stdout/stderr to a file but show stderr on terminalexec >file.log 2> >(tee >(cat >&3))# function echo to show echo output on terminalecho() {   # call actual echo command and redirect output to fd=3   command echo "$@" >&3}# script starts hereecho "show me"printf "=====================\n"printf "%s\n" "hide me"ls foo-foodatettyecho "end of run"# close fd=3exec 3>&-

After you run your script it will display following on terminal:

show mels: cannot access 'foo-foo': No such file or directoryend of run

If you do cat file.log then it shows:

=====================hide mels: cannot access 'foo-foo': No such file or directoryFri Dec  2 14:20:47 EST 2016/dev/ttys002
  • On terminal we're only getting output of echo command and all the errors.
  • In the log file we're getting error and remaining output from script.