I've read man on exec, but still don't understand the consequences of the two following lines in the script I'm studying:

exec >> >(tee -a $logfile)
exec 2>&1

I've read this answer, but still have doubts.

My understanding is that first line makes >> output (append) also to $logfile in addition whatever is to the right of >> further in the script file.

The second line will make output to 2 (stderr) be redirected to 1 (stdout) further in the script.

  1. Is my understanding correct?
  2. How to undo the above commands so behavior after undoing is the same as it was before those two lines were executed?
  3. Lets say further in the script we start some app in background e.g. someapp &. I want to run this command in terminal - separately and independently from the script - with the same effect as if it runs in the script. How should I modify someapp & to have redirections set with execs above?
  • see unix.stackexchange.com/q/634350/330217 for how to save and restore stdout
    – Bodo
    Commented Jan 12, 2023 at 18:08
  • To wit, in the linked question, exec 7>&1 duplicates stdout (file descriptor 1) on file descriptor 7 so that it can later be restored with exec 1>&7; exec 7>&-
    – tripleee
    Commented Jan 12, 2023 at 19:41

1 Answer 1

exec >> >(tee -a $logfile)

Short for:

exec 1>> >(tee -a $logfile)

Does the equivalent of:

exec 1>> /dev/fd/x

Where x is a file descriptor that points to the writing end of the pipe.

Before that, bash has started a child process with its fd 0 (stdin) connected to the other end of the pipe which meanwhile is busy executing tee.

exec 1>> file, opens the file with O_APPEND and without O_TRUNC, and moves the resulting fd to 1.

opening /dev/fd/x, depending on the system is like doing a dup(x) (most) or opening the same file as open on fd x (Linux and cygwin only). Here, with fd x being opened on a pipe, it makes no difference, and the O_APPEND and O_TRUNCATE flags are irrelevant, so it's the same as exec > >(...).

It's a bit beside the point but tee -a $logfile is incorrect and should have been tee -a -- "$logfile" if the intent was to open the file whose path is stored in $logfile with O_APPEND.

So after that command, fd 1 in the shell will be pointing to a pipe. At the other end of the pipe, tee reads what's coming and tees it to both the end of $logfile and to what stdout was pointing to before the redirection (maybe a terminal device or something else if the output of your script was redirected one way or another).

exec 2>&1

Makes fd 2 point to the same thing as fd 1, so that same pipe.

To be able to under that, you'd have had to save the open file description the fds 1 and 2 were open on on separate fds before doing the redirection:

exec 3>&1 4>&2 > >(tee -a -- "$logfile") 2>&1

Where 3>&1 does a dup2(1, 3) so fd 3 now points to the same open file description as fd 1 did.

And to undo,

exec >&3 2>&4 3>&- 4>&-

Or to run someapp with its stdout and stderr being the original stdout and stderr:

someapp >&3 2>&4 3>&- 4>&- &

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .