Bourne | Ash |  #!  | find | ARG_MAX | Shells | whatshell | portability | permissions | UUOC | ancient | - | ../Various | HOME
"$@" | echo/printf | set -e | test | tty defs | tty chars | $() vs ) | IFS | using siginfo | nanosleep | line charset | locale


Internal usage of file descriptor 19


The Bourne shell makes use of file descriptor 19 for internal purposes: If the shell is called with a script as argument (which also applies to the usage of the #! mechanism), then it opens file descriptor 19 with the file to read it - without checking if this file descriptor was in use already.

Usually, you won't notice that, because it's not possible to use or redirect file descriptors higher than 9 (single digit) in the shell.

However, if the file descriptor was opened in advance and another process, being started through a Bourne shell script, expects this file descriptor still to be open, then it will fail, because the interposed shell closed it.

This can be demonstrated with a program listing open file descriptors ("list-fd", source), or with utilities like lsof(8).

   $ exec 19>&1       # Redirect file descriptor 19 to where stdout is pointing to.
                      # Execute this command in a modern bourne compatible shell,
                      # because the traditional bourne shell doesn't allow it.

   $ ./list-fd        # Confirm the redirection with a program.
   FD   0:  O_RDWR
   FD   1:  O_RDWR
   FD   2:  O_RDWR
   FD  19:  O_RDWR

   $ cat script.sh    # This is a shell script calling that program
   #!/bin/sh          # ... with the #! mechanism pointing to your Bourne shell
   ./list-fd

   $ ./script.sh      # Start it through the #! mechanism: File descriptor 19 was closed by the interpreter,
   FD   0:  O_RDWR
   FD   1:  O_RDWR
   FD   2:  O_RDWR

   $ sh ./script.sh   # or directly call a traditional bourne shell as interpreter: ...dito,
   FD   0:  O_RDWR
   FD   1:  O_RDWR
   FD   2:  O_RDWR

   $ bash ./script.sh  # in other shells (bash, ksh, etc.) file descriptor 19 is still open:
   FD   0:  O_RDWR
   FD   1:  O_RDWR
   FD   2:  O_RDWR
   FD  19:  O_RDWR

A few variants changed this:
It was fixed on SCO Unix 32v42 (and its successors Open Desktop 3 and OpenServer 5).
On HP-UX it was not fixed, but slightly improved: fd 59 is hardcoded instead.