30

In a bash script, how can I redirect all standard outputs to a log file and tee the output on the screen using exec ?

log_file="$HOME/logs/install.txt-`date +'%Y-%m-%d_%H-%M-%S'`"
[ -f "$log_file" ] || touch "$log_file"
exec 1>> $log_file 2>&1

This code redirect all the log to the log file but not to the screen .

  • 1
    May be the answer looks the same, but it was not the same question. – 4m1nh4j1 Jul 21 '14 at 8:28
  • No, it is the exact same question. The first sentence describes what it's trying to do, and it's exactly what you're trying to do: "redirect all output to one file, debug log as well as to the terminal" – Patrick Jul 21 '14 at 12:44
61

Use process substitution with & redirection and exec:

exec &> >(tee -a "$log_file")
echo "This will be logged to the file and to the screen"

$log_file will contain the output of the script and any subprocesses, and the output will also be printed to the screen.

  • >(...) starts the process ... and returns a file representing its standard input.

  • exec &> ... redirects both standard output and standard error into ... for the remainder of the script (use just exec > ... for stdout only).

  • tee -a appends its standard input to the file, and also prints it to the screen.

| improve this answer | |
  • 1
    It works, but sometimes I still get output when I already have my console prompt, resulting in a mixed output. – Halfgaar Oct 28 '15 at 9:15
  • 1
    @Halfgaar - That is expected as exec replace the process including file descriptors for STDIN, STDOUT and STDERR - effectively detaching it from the terminal but tee continues to emit anything it receives. – shalomb Mar 29 '16 at 9:55
8
exec >> $log_file 2>&1 && tail $log_file
| improve this answer | |

Not the answer you're looking for? Browse other questions tagged or ask your own question.