Bash – Explain exec and tee to Logfile Commands

bash

I saw this at the top of my bash script file:

export LOGFILE=$LOGDIRECTORY/${SCRIPT_NAME}.log
exec > >(tee $LOGFILE)
exec 2>&1

What does it do? What are two exec processes doing here? I realize that keeping it like this, all the output of the execution of the script is piped to $LOGFILE but I wanted to understand from the perspective of the exec statements.

Best Answer

In shells, exec does 1) file openings and redirections 2) actual execing (replacing the current process image with another process image).

These execs are redirections.

First you redirect (exec 1> >(tee $LOGFILE)) the stdout descriptor (1) to a process substitution-generated pipe connected to a concurrently run tee process that has $LOGFILE as its first argument and then you redirect the stderr descriptor (2) to the same place as where descriptor 1 now points (the tee pipe).

Keeping in mind that filedescriptors get inherited, you've just made all future stdout and stderr output go to the tee process, which writes it to $LOGFILE and to wherever filedescriptor 1 pointed to originally (probably your terminal).


Note: The tee process outputs to the original stdout (=the original filedescriptor 1) because, as you can learn from /searching bash(1) for Simple Command Expansion and Process Substitution, process substitution ( >() <() ) happens (along with other expansions) before redirections get executed, which means that the redirection in exec 1> >(tee "$LOGFILE") happens after tee has started, leaving tee with the same filedescriptor 1 that it inherited from the parent shell. (If it were the other way around, tee would be made to write to its own input, which might make it deadlock, depending on its IO pattern).

Related Question