Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Mixing and multiple redirection of stderr/stdout



Am 18.05.2011 um 07:13 schrieb Aaron Davies:

> On Tuesday, May 17, 2011, Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
> 
>> The next trick is that zsh has a shorthand operator ">&" (no numbers
>> around it) that means "redirect both stdout and stderr at the same
>> time".  This is done without destroying one of the original streams
>> in the way that happens when you use "2>&1".  So:
>> 
>> torch% script >&file_mix >file_out 2>file_err
>> file_out:STDOUT
>> file_mix:STDOUT
>> file_mix:STDERR
>> file_err:STDERR
>> 
>> And there you are.
> 
> Relatedly, can these (or any other) redirections guarantee the same
> interleaving of stdout and stderr that would be produced on the
> console with no redirections? I've often seen (mostly in other shells,
> iirc) that a process which would have, e.g., alternating prints to out
> and err, is captured to file as one long block of out followed by one
> long block of err.

Unfortunately I exactly encounter this problem now.  I am trying to apply
the trick Bart described as follows:

1) My example scripts echos some text to standard output.  The script
itself is a shell script which runs in verbose-mode.  Hence, every command
gets echoed to standard error before it gets executed:

----------------------------------------------------------------
zsh% cat script.sh 
#! /bin/zsh -v

echo 'Hello world!'
echo 'Hello world!'
----------------------------------------------------------------

2) If I just run the script I get the following output (where stdout and stderr
are mixed):

----------------------------------------------------------------
zsh% ./script.sh 
# system-wide environment settings for zsh(1)
if [ -x /usr/libexec/path_helper ]; then
	eval `/usr/libexec/path_helper -s`
fi
#! /bin/zsh -v

echo 'Hello world!'
Hello world!
echo 'Hello world!'
Hello world!
----------------------------------------------------------------

3) However, when I try mixing stdout&stderr and in addition try to redirect
stdout to a file I get random results in "file_mix".  For example   

----------------------------------------------------------------
zsh% ./script.sh >&file_mix >file_out           
zsh% cat file_mix 
# system-wide environment settings for zsh(1)
if [ -x /usr/libexec/path_helper ]; then
	eval `/usr/libexec/path_helper -s`
fi
#! /bin/zsh -v

echo 'Hello world!'
echo 'Hello world!'
Hello world!
Hello world!
----------------------------------------------------------------

This is just like when you would mix stdout and stderr by

	./script.sh >file_mix 2>file_mix

In this case this random behavior is clear.  We open the
file "file_mix" twice and therefore have two independent
entries in the open file table (one associated with stdout,
the other with stderr).

When one mixes the output by

	./script.sh >file_mix 2>&1

we only have one entry on the open file table for "file_mix"
and two file descriptors point the this entry.  Hence, the
outputs are mixed the right way (as they would be displayed
on the console).

So can something like my "mixing stdout&stderr but also redirect
stdout, stderr separately to files" work at all?  The longer I think
about it the more I am confused how it could be realized technically.
I guess it can not be done by using "open, close, dup and co" internally.
Or am I wrong?


Michael


Messages sorted by: Reverse Date, Date, Thread, Author