To understand what's happening one must know, that in order for bash to print anything that is send to stdout (which is the file descriptor 1) it sets the file descriptor 1 to the current terminal. This is nicely explained here https://catonmat.net/bash-one-liners-explained-part-three.
&> output
replaces the terminal in file descriptor 1 and 2 with the file output
. So there is no file descriptor left, to which echo "..."
could send that would be displayed in the terminal. Hence, we have two possible solutions:
Redirecting to the current terminal
This works with the utility tty
that returns the current user terminal.
#!/bin/bash
trap_function(){
trap '' EXIT INT TERM
echo "This is redirected to 'output'." &>$(tty)
touch this_will_exist
}
trap trap_function EXIT INT TERM
eval "sleep 100" &> output
However, it may not be possible to capture this output with a wrapper.
Redirecting over another file descriptor
This solution requires that an additional file descriptor is set to the current terminal (e.g., 123). We can simply use what is already set in the file descriptor 1 before we replace it with output
by 123>&1
. Then we can set the file descriptor of echo
(which is stdout) to what we stored in file descriptor 123:
#!/bin/bash
trap_function(){
trap '' EXIT INT TERM
echo "This is redirected to 'output'." >&123
touch this_will_exist
}
trap trap_function EXIT INT TERM
eval "sleep 100" 123>&1 &> output