Send stdout and stderr to file, syslog, and terminal

Add a nested process substitution and another tee in there like:

exec &> >(tee >(tee "/tmp/box-setup.log" | logger -t box-setup))

The first tee within the main process substitution sends STDOUT/STDERR to terminal and also to the nested process substitution, the tee inside that saves the content in file /tmp/box-setup.log and the pipe is used to send the output to logger's STDIN too.


I'm completely blind because the console is blank as the bash script executes.

You might want to solve that problem a different way: run your bash script in the background, and run less /tmp/box-setup.log and hit F to keep updating the screen as lines are added to the file it's watching (like tail -f).

If running the script in the background is a problem, use tmux or screen to get multiple sessions multiplexed onto one ssh connection. Use the same less command in another shell.


The original problem:

tee can copy to multiple destinations. Make one of them the terminal, using the /dev/tty special file. I think it always refers to the controlling tty of the current process. Or probably better, to /dev/stderr, since tee's stderr is still connected to the shell's stderr. (This lets you silence the script with &> /dev/null).

exec &> >(tee /dev/stderr "/tmp/box-setup.log" | logger -t box-setup)

BTW, this is equivalent to but more efficient than (tee /dev/stderr | tee "/tmp/box-setup.log" | logger ...).

It would be possible to use some file-descriptor cloning to give tee the original script's stdout, rather than stderr.