Reputation: 1202
Is it possible within a bash script, to make all output, except the output i specifically output with echo, go to a log file, BUT if there's errors in the output it should show in the terminal (and the log file also ofcourse)?
Upvotes: 2
Views: 6299
Reputation: 785108
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 terminal
exec >file.log 2> >(tee >(cat >&3))
# function echo to show echo output on terminal
echo() {
# call actual echo command and redirect output to fd=3
command echo "$@" >&3
}
# script starts here
echo "show me"
printf "=====================\n"
printf "%s\n" "hide me"
ls foo-foo
date
tty
echo "end of run"
# close fd=3
exec 3>&-
After you run your script it will display following on terminal:
show me
ls: cannot access 'foo-foo': No such file or directory
end of run
If you do cat file.log
then it shows:
=====================
hide me
ls: cannot access 'foo-foo': No such file or directory
Fri Dec 2 14:20:47 EST 2016
/dev/ttys002
echo
command and all the errors.Upvotes: 4
Reputation: 41223
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.
Upvotes: 3