2

For a bash script project, I write human-readable log info to stdout/stderr. Additionally, I want to write formatted metrics to a third stream that will be discarded by default but can be redirected for piped processing. Is the approach doing this with an additional file descriptor advised?

exec 3> /dev/null
echo "This is stdout"
echo "This is stderr" >&2
echo "This is fd3" >&3

I'm fine with the third line not showing up under normal conditions. However, when used in a certain toolchain I want to pipe these messages. Simple example:

$ bash example.sh 3>&1
This is stdout
This is stderr

The third line does not appear as the console output.

What am I doing wrong? Is there a solution to this? Is another approach advised?

1

Fd 3 is bound to /dev/null in the first line, therefore the third Echo inevitally has its standard output redirected to /dev/null.

Instead, verify if Fd 3 has been assigned by checking the existance of /proc/self/fd/3. If not, then bind it to /dev/null. If yes, leave it alone.

[ -e /proc/self/fd/3 ] || exec 3> /dev/null
echo "This is stdout"
echo "This is stderr" >&2
echo "This is fd3" >&3
$ ./example.sh 3>&1
This is stdout
This is stderr
This is fd3
$ ./example.sh
This is stdout
This is stderr

If the third Echo is actually a command that writes a lot of output, a more efficient alternative is to simply only trigger the command if the Fd 3 is open.

echo "This is stdout"
echo "This is stderr" >&2
[ -e /proc/self/fd/3 ] && echo "This is fd3" >&3

Other possibility is to always redirect via Fd 3 to a file or FIFO, and only read it if you want on the calling process, but this would also imply in unnecessary time penalties if that output is not being used.

5
  • Thanks for your answer! What I am still unsure about is, whether this is a good idea to solve my problem. Could writing to &3 have unwanted side effects? – Mazzen Nov 7 '20 at 13:04
  • @Mazzen You are welcome! Do you have any unwanted side effect in mind? I don't know any, except for maybe a noticiable longer execution time if you are writing a lot to /dev/null. In that case, you could simply transfer the if test to the statement that writes to fd 3 and simply don't write if the fd is not assigned. – Quasímodo Nov 7 '20 at 13:10
  • I was wondering if any linux derivitive or distribution might run a certain service on fd 3. I don't think this won't be a performance issue. The application just prints a few messages to stdout and I want to add a postprocessible version of these messages in json to fd 3 to be consumed by another application. – Mazzen Nov 7 '20 at 13:23
  • @Mazzen Each process has its own sets of file descriptors (as you can see each PID inside /proc has its own fd directory), so it is irrelevant if some other process X also uses Fd 3, because it is not related to your process Y. All you need is to guarantee no program inside your script outputs to Fd 3 (I have never met any that does). – Quasímodo Nov 7 '20 at 13:34
  • Amazing thank you. So fd3 is an option and I'll discuss with the team whether it's a the path we want to take. Best! – Mazzen Nov 7 '20 at 14:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.