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 echo
s 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.