Writing outputs to log file and console Writing outputs to log file and console bash bash

Writing outputs to log file and console


exec 3>&1 1>>${LOG_FILE} 2>&1

would send stdout and stderr output into the log file, but would also leave you with fd 3 connected to the console, so you can do

echo "Some console message" 1>&3

to write a message just to the console, or

echo "Some console and log file message" | tee /dev/fd/3

to write a message to both the console and the log file - tee sends its output to both its own fd 1 (which here is the LOG_FILE) and the file you told it to write to (which here is fd 3, i.e. the console).

Example:

exec 3>&1 1>>${LOG_FILE} 2>&1echo "This is stdout"echo "This is stderr" 1>&2echo "This is the console (fd 3)" 1>&3echo "This is both the log and the console" | tee /dev/fd/3

would print

This is the console (fd 3)This is both the log and the console

on the console and put

This is stdoutThis is stderrThis is both the log and the console

into the log file.


Yes, you want to use tee:

tee - read from standard input and write to standard output and files

Just pipe your command to tee and pass the file as an argument, like so:

exec 1 | tee ${LOG_FILE}exec 2 | tee ${LOG_FILE}

This both prints the output to the STDOUT and writes the same output to a log file. See man tee for more information.

Note that this won't write stderr to the log file, so if you want to combine the two streams then use:

exec 1 2>&1 | tee ${LOG_FILE}


I tried joonty's answer, but I also got the

exec: 1: not found

error. This is what works best for me (confirmed to work in zsh also):

#!/bin/bashLOG_FILE=/tmp/both.logexec > >(tee ${LOG_FILE}) 2>&1echo "this is stdout"chmmm 77 /makeError

The file /tmp/both.log afterwards contains

this is stdoutchmmm command not found 

The /tmp/both.log is appended unless you remove the -a from tee.

Hint: >(...) is a process substitution. It lets the exec to the tee command as if it were a file.