3

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 Answer 1

2

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
    Commented Nov 7, 2020 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
    Commented Nov 7, 2020 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
    Commented Nov 7, 2020 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
    Commented Nov 7, 2020 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
    Commented Nov 7, 2020 at 14:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .