I'm trying to use bash to open a new descriptor for writing extra diagnostic messages. I don't want to use stderr, because stderr should only contain output from the programs called by bash. I also want my custom descriptor to be redirectable by the user.
I tried this:
exec 3>/dev/tty
echo foo1
echo foo2 >&2
echo foo3 >&3
But when I try to redirect fd 3, the output still writes to the terminal.
$ ./test.sh >/dev/null 2>/dev/null 3>/dev/null
foo3
First the parent shell sets file descriptor 3 to /dev/null
Then your program sets file descriptor 3 to /dev/tty
So your symptoms are not really surprising.
Edit: You could check to see if fd 3 has been set:
if [[ ! -e /proc/$$/fd/3 ]]
then
exec 3>/dev/tty
fi
Simple enough: If the parent shell is not redirecting fd 3, then test.sh
will be redirecting fd 3 to /dev/tty
.
if ! { exec 0>&3; } 1>/dev/null 2>&1; then
exec 3>/dev/tty
fi
echo foo1
echo foo2 >&2
echo foo3 >&3
Here's a way to check if a file descriptor has already been set using the (Bash) shell only.
(
# cf. "How to check if file descriptor exists?",
# http://www.linuxmisc.com/12-unix-shell/b451b17da3906edb.htm
exec 3<<<hello
# open file descriptors get inherited by child processes,
# so we can use a subshell to test for existence of fd 3
(exec 0>&3) 1>/dev/null 2>&1 &&
{ echo bash: fd exists; fdexists=true; } ||
{ echo bash: fd does NOT exists; fdexists=false; }
perl -e 'open(TMPOUT, ">&3") or die' 1>/dev/null 2>&1 &&
echo perl: fd exists || echo perl: fd does NOT exist
${fdexists} && cat <&3
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With