Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 10 Sep 1997 13:39:52 +0100
From:      nik@iii.co.uk
To:        Greg Pavelcak <gpavelcak@philos.umass.edu>
Cc:        questions@freebsd.org
Subject:   Re: Redirecting "make world" Output
Message-ID:  <19970910133952.00934@strand.iii.co.uk>
In-Reply-To: <Pine.OSF.3.96.970910073134.26194A-100000@emily.oit.umass.edu>; from Greg Pavelcak on Wed, Sep 10, 1997 at 07:37:46AM -0400
References:  <Pine.OSF.3.96.970910073134.26194A-100000@emily.oit.umass.edu>

next in thread | previous in thread | raw e-mail | index | archive | help
[Copied to the mailing list for posterity]

On Wed, Sep 10, 1997 at 07:37:46AM -0400, Greg Pavelcak wrote:
> I believe the upgrade tutorial says you can save the info output of
> make world by redirecting like this (using sh as shell):
> 
> 	make world 2>&1 | tee /var/tmp/mw.out
> 
> I saw this 2>&1 construction in the sh man pages but I don't
> understand it. Anyway, the immediate problem is that I get an error
> when I write this. I think it said "ambiguous redirection"
> unfortunately I don't have it with me now.

Hmm. That construct works exactly as shown, under 'sh' as the shell.
If you use csh (or tcsh) it does indeed fail with "Ambiguous output
redirect".

Check which shell you're using, 

    % echo $SHELL
    /usr/local/bin/tcsh

If it doesn't say "/bin/sh", run sh.

The actual redirection works as follows:

  When a Unix program starts up, 3 file descriptors are opened for it.
  Each file descriptor has a number. By convention[1], descriptor 0 is 
  STDIN, 1 is STDOUT and 2 is STDERR.

  When a program reads user input, it (by default) reads from STDIN. When
  it writes output it writes it to STDOUT, and when it writes errors it
  sends them to STDERR.

  This lets you do input/output redirection. For example, when you run

      % ls > /tmp/ls.out

  the shell starts 'ls', but starts it with descriptor 1 (STDOUT) redirected
  to a file instead of the terminal. A similar thing happens if you do

      % grep foo < /tmp/ls.out

  (ignoring the fact that you could just specify the filename on grep's
  command line) except that the shell arranges for descriptor 0 (STDIN)
  to the file /tmp/ls.out instead of the terminal.

  STDERR comes into play when programs want to report errors, but they
  don't want those errors to be mixed in with their regular output.

  For example, 

      % grep foo non_existant_file > /tmp/grep.out

  will echo "grep: non_existant_file: No such file or directory" to the
  terminal. The line will *not* be put in /tmp/grep.out. grep explicitly
  wrote it's error message to STDERR rather than STDOUT[2].

  This is useful, because it allows you to redirect a command's normal 
  output, but get an immediate view of any errors it might produce.

  Of course, if a command generates lots of errors, they might scroll off
  the screen and be lost (forgetting about the FreeBSD console's ability
  to scrollback with the Scroll Lock key for a moment). For a command
  like "make world" this is a bad thing.

  The (sh) construct 

      % program_1 2>&1 | program_2

  runs 'program_1' and makes a copy of any messages that program sends to
  STDERR to STDOUT. Messages to STDERR are still sent to the console as
  normal, they're just copied to STDOUT too.

  'program_2' can then read from STDIN and receive all the output from
  'program_1', regardless of whether or not it was sent (originally) to
  STDOUT or STDERR.

  The construct is saying "Take any output from descriptor 2 (STDERR) and
  duplicate it in to descriptor 1 (STDOUT)."

  At least, that's how it works if you use 'sh' as the shell. csh has a
  smaller, more restrictive syntax that doesn't let you do as many fun
  things with redirection. However, in this case the construct

      % program_1 |& program_2

  is equivalent.

Hope that makes sense.

N

[1] This may actually be documented in a standard somewhere, but I don't 
    know where.

[2] A program must be written to do this. It doesn't happen automatically. 
    Try

       % ls non_existant_file > /tmp/ls.out

    No output will be shown on the terminal. /tmp/ls.out will contain the
    line

       non_existant_file: No such file or directory.

    This is (arguably) a bug in ls.
-- 
--+==[ Nik Clayton is Just Another Perl Hacker at Interactive Investor ]==+--
        Diana, the roadkill formally known as Princess, 1961-1997    NC5-RIPE



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19970910133952.00934>