1
\$\begingroup\$

Is this the best way to prefix all lines written by a Bash script to standard error?

#! /bin/bash

exec 3>&2
exec 2> >(sed 's/^/ERROR: /' >&3)

echo stdout
echo stderr >&2

I am wondering, if I have to close file descriptor 3.

\$\endgroup\$
7
\$\begingroup\$

There's not a lot to review here. It's Valgrind clean, though that's not difficult to achieve.

Certainly consider closing stream 3, unless you want to keep a means to emit unprefixed stderr messages.

One shortcoming is that the shell won't wait for sed to finish when it terminates. If the last process's output is still being filtered at this point, then you may fail to capture it - I observed this (repeatably) when running the program in Emacs compilation-mode.

One way you can improve on this if you're using GNU sed is by passing -u ("unbuffered") flag to sed. If you don't have GNU sed but do have GNU coreutils, then the stdbuf utility could make sed line-buffered for you:

stdbuf -oL -iL sed 's/^/ERROR: /'

With any sed, we could (and should) close stderr when we terminate and wait for sed to finish to be sure of catching all error output.


Modified code

#!/bin/bash

exec 3>&2
exec 2> >(sed -u 's/^/ERROR: /' >&3)
exec 3>&-
# shellcheck disable=SC2064
trap "exec 2>&-; wait $!" EXIT

echo stdout
echo stderr >&2
|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ It is possible to wait for the process substitution. The pid of the child process is in $! after the exec. In order to flush the output of the child process, it is sufficient to close the input fd, which is fd 2 of the parent. After that one can wait for the child pid. \$\endgroup\$ – ceving Jan 29 at 13:28
  • \$\begingroup\$ Good suggestion; thanks @ceving. I've made the appropriate change. \$\endgroup\$ – Toby Speight Jan 29 at 17:11
  • \$\begingroup\$ That was a typo - &1 where I meant &-. Sorry! \$\endgroup\$ – Toby Speight Jan 29 at 17:12

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.