This is related but orthogonal to my earlier question.
Consider the following shell script, which I'll put in a file called Play.sh.
#!/bin/bash
echo "Send me to standard out"
echo "Send me to standard err" >&2
When I run this, I can redirect stdout and stderr.
$ ./Play.sh > /dev/null
Send me to standard err
$ ./Play.sh 2> /dev/null
Send me to standard out
All this works as desired.
I would like to open a third stream and force echo
to output to the third stream, so I can filter to it. Something like the following:
#!/bin/bash
echo "Send me to standard out"
echo "Send me to standard err" >&2
echo "Send me to stream 3" >&3
Unfortunately, the third stream does not attach to /dev/tty
by default.
Observed Output
# This works as desired
./Play.sh 3> /dev/null
Send me to standard out
Send me to standard err
# This does not work as desired.
$ ./Play.sh
Send me to standard out
Send me to standard err
./Play.sh: line 5: 3: Bad file descriptor
Desired Output
# This works as desired
./Play.sh 3> /dev/null
Send me to standard out
Send me to standard err
# I would like stream 3 to go to /dev/tty ONLY when not redirected.
$ ./Play.sh
Send me to standard out
Send me to standard err
Send me to stream 3
Is there an incantation I can use inside the shell script to make the third stream point at /dev/tty if and only if the parent process does not redirect it?
Effectively, I'd like the third stream to behave exactly the same way as stdout
and stderr
: Default to /dev/tty
and allow the parent to redirect.
CodePudding user response:
The file descriptor 3
inside Play.sh and the 3
in ./Play.sh 3> /dev/null
are not related because they belong to different processes.
What you can do is to pass the destination into Play.sh:
#!/bin/bash
third_stream="$1"
exec 3>$third_stream
echo "Send me to standard out"
echo "Send me to standard err" >&2
echo "Send me to stream 3" >&3
then call it with :
./Play.sh /dev/null
CodePudding user response:
For completeness, based on tripleee's comment, what I actually wanted was the following:
#!/bin/bash
echo "Send me to standard out"
echo "Send me to standard err" >&2
if ! (printf '' 1>&3) 2>&-; then
# File descriptor 3 is not open
# Option 1: Redirect fd3 to stdout.
exec 3>&1
# Option 2: Redirect fd3 to /dev/null.
# exec 3>/dev/null
fi
# No error here.
echo "Send me to stream 3" >&3
With this modification, a parent process can redirect 3 when it desires to do so, and otherwise have it as part of stdout.
$ ./Play.sh
Send me to standard out
Send me to standard err
Send me to stream 3
$ ./Play.sh 3> /dev/null
Send me to standard out
Send me to standard err