(autoconf.info)File Descriptors


Next: File System Conventions Prev: Here-Documents Up: Portable Shell

10.3 File Descriptors
=====================

Most shells, if not all (including Bash, Zsh, Ash), output traces on
stderr, even for subshells.  This might result in undesirable content
if you meant to capture the standard-error output of the inner command:

     $ ash -x -c '(eval "echo foo >&2") 2>stderr'
     $ cat stderr
     + eval echo foo >&2
     + echo foo
     foo
     $ bash -x -c '(eval "echo foo >&2") 2>stderr'
     $ cat stderr
     + eval 'echo foo >&2'
     ++ echo foo
     foo
     $ zsh -x -c '(eval "echo foo >&2") 2>stderr'
     # Traces on startup files deleted here.
     $ cat stderr
     +zsh:1> eval echo foo >&2
     +zsh:1> echo foo
     foo

One workaround is to grep out uninteresting lines, hoping not to remove
good ones.

   If you intend to redirect both standard error and standard output,
redirect standard output first.  This works better with HP-UX, since
its shell mishandles tracing if standard error is redirected first:

     $ sh -x -c ': 2>err >out'
     + :
     + 2> err $ cat err
     1> out

   Don't try to redirect the standard error of a command substitution.
It must be done _inside_ the command substitution.  When running `: `cd
/zorglub` 2>/dev/null' expect the error message to escape, while `: `cd
/zorglub 2>/dev/null`' works properly.

   It is worth noting that Zsh (but not Ash nor Bash) makes it possible
in assignments though: `foo=`cd /zorglub` 2>/dev/null'.

   When catering to old systems, don't redirect the same file descriptor
several times, as you are doomed to failure under Ultrix.

     ULTRIX V4.4 (Rev. 69) System #31: Thu Aug 10 19:42:23 GMT 1995
     UWS V4.4 (Rev. 11)
     $ eval 'echo matter >fullness' >void
     illegal io
     $ eval '(echo matter >fullness)' >void
     illegal io
     $ (eval '(echo matter >fullness)') >void
     Ambiguous output redirect.

In each case the expected result is of course `fullness' containing
`matter' and `void' being empty.  However, this bug is probably not of
practical concern to modern platforms.

   Don't rely on file descriptors 0, 1, and 2 remaining closed in a
subsidiary program.  If any of these descriptors is closed, the
operating system may open an unspecified file for the descriptor in the
new process image.  Posix says this may be done only if the subsidiary
program is set-user-ID or set-group-ID, but HP-UX 11.23 does it even
for ordinary programs.

   Don't rely on open file descriptors being open in child processes.
In `ksh', file descriptors above 2 which are opened using `exec N>file'
are closed by a subsequent `exec' (such as that involved in the
fork-and-exec which runs a program or script).  Thus, using `sh', we
have:

     $ cat ./descrips
     #!/bin/sh -
     echo hello >&5
     $ exec 5>t
     $ ./descrips
     $ cat t
     hello
     $

But using ksh:

     $ exec 5>t
     $ ./descrips
     hello
     $ cat t
     $

Within the process which runs the `descrips' script, file descriptor 5
is closed.

   DOS variants cannot rename or remove open files, such as in `mv foo
bar >foo' or `rm foo >foo', even though this is perfectly portable
among Posix hosts.

   A few ancient systems reserved some file descriptors.  By convention,
file descriptor 3 was opened to `/dev/tty' when you logged into Eighth
Edition (1985) through Tenth Edition Unix (1989).  File descriptor 4
had a special use on the Stardent/Kubota Titan (circa 1990), though we
don't now remember what it was.  Both these systems are obsolete, so
it's now safe to treat file descriptors 3 and 4 like any other file
descriptors.


automatically generated by info2www