I'd like to know why bash doesn't display an error message when we refer to a closed stderr. When it comes to other file descriptors, they have to be opened if we want to, for example, duplicate them. Stderr seems to be kinda special in this case:

$ cat file_1
echo Test1 1>&5
$ cat file_2
echo Test2 1>&2

$ ./file_1 5>&-
./file_1: line 1: 5: Bad file descriptor
$ ./file_1 5>&1
$ ./file_2 2>&-
$ #NO ERROR and no output!
$ ./file_2

Why does the shell allow it?

  • Because stdin, stdout, and stderr (0, 1, 2) are assumed open for any process by default, and bash arranges this for its children?
    – vonbrand
    Feb 18 '13 at 4:07
  • How do you explain these: echo test 2>&- 1>&2 #ok and echo test 1>&- 2>&1 #error
    – Quentin
    Feb 18 '13 at 4:12

Where would the error be sent when running file_2?

When you type ./file_2 (with said file executable), the system actually runs /bin/sh ./file_2 -- i.e. it's running a new copy of /bin/sh, which is responsible for running the commands in ./file2, and for reporting the errors it finds there, outputting them to stderr.

But you've just run that /bin/sh with stderr closed. So it wants to emit an error, but has nowhere to do so.

Which you can verify with:

$ strace -e write,dup2 -fo /dev/stdout sh -c 'echo foo >&2' 2>&-
8785  dup2(2, 1)                        = -1 EBADF (Bad file descriptor)
8785  write(2, "sh: 1: ", 7)            = -1 EBADF (Bad file descriptor)
8785  write(2, "2: Bad file descriptor", 22) = -1 EBADF (Bad file descriptor)

The dup2 fails because fd 2 is closed, sh tries to report the error on stderr, but that fails as well as stderr (fd 2) is closed.

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.