[comp.unix.wizards] Redirecting shell output.

jc@minya.UUCP (John Chambers) (10/18/87)

Hi, folks.  Here's my shell puzzle of the day.  We all learn in our first
hour of Unix lessons how to redirect input and output of any command that
is started by a shell.  What I'd like to know is:  Is there a "right" way
to tell the shell to redirect the output of ALL subsequent commands to a
file?

My motivation is as follows.  Like some of you, I have written scripts that
aren't, let's say, totally perfect the first time.  Something really hard
to debug is a script that works fine when I run it, but doesn't work so fine
when someone else (like cron, maybe) runs it.  

What I'd like to do is to arrange it so that the program redirects its own
output to an "audit trail" for my perusal.  I don't want to bother the poor
user with all the garbage output; I'd rather have it done quietly, with no
fuss or bother.  For C programs, this is easy:
	close(1); 
	open("/aud/fubar",2);
	close(2); 
	dup(1);
for instance.  For scripts, it's not so easy.  What I find myself doing a
lot is having one script, "foo", that looks like:
	exec bar >/aud/foo 2>&1
with the real work in the "bar" script.  This works just fine, but it seems
a rather clumsy approach.  I have two scripts where one would do, the "foo"
script occupies a whole 1K disk block (and an inode and a directory entry)
unnecessarily, and the kernel is bothered with a totally unneeded exec.

What I'd like is to write the "bar" script so that it starts with something
equivalent to the above four lines of C.  But I can't find anything in the
sh(1) pages, or in the shell teaching documents, that explains how to do
file opens and closes in the shell language.

Any hints?  Or is this just a deficiency in the language that I'll have 
to learn to live with?  I mean, it's not a big deal to have one script
exec another.  It just seems like a silly kludge that wastes my and the
machine's time and makes the code look awkward.  That's unaesthetic.

-- 
John Chambers <{adelie,ima,maynard,mit-eddie}!minya!{jc,root}> (617/484-6393)

c188-bl@katerina.uucp (Steven Brian McKechnie Sargent) (10/19/87)

Try the "exec" command of the Shell.  The full syntax is
	exec [command] [redirections]
[Redirections] is optional, in which case [command] runs with the default I/O;
what most people don't know is that [command] is also optional, in which
case [redirections] are applied to the running shell.  So if you say words
like
	exec 2>thump
all standard-error redirections go to a file named "thump."  Saying words like
	exec 14 >&2
	exec 2>thump
will save the old value of 2 in 14, redirect 2 into "thump."  Later you can
undo this with
	exec 2>&14
	exec 14>&-
which restores 2 from 14 and then closes 14.

All this is documented in sh(1), but so tersely that you can skip right over
it and never notice.

S.

dave@lsuc.UUCP (10/20/87)

In article <289@minya.UUCP>, jc@minya.UUCP (John Chambers) writes:
> 					Is there a "right" way
> to tell the shell to redirect the output of ALL subsequent commands to a
> file?

We ran into this when running stuff at startup from /etc/rc (on a
v7-based system, not that it matters).  I found all those ">/dev/console"s
a bit ugly.  Mark Brader, {lsuc,sq}!msb suggested:

exec sh <<'_UNTIL_THE_END_OF_THIS_FILE_' >/dev/console 2>&1

which we've been using for years now.  Note that sh doesn't
ever need to find the _UNTIL_etc. string; if it encounters
EOF it exits happily.

David Sherman
The Law Society of Upper Canada
Toronto
-- 
{ uunet!mnetor  pyramid!utai  decvax!utcsri  ihnp4!utzoo } !lsuc!dave
Pronounce it ell-ess-you-see, please...

allbery@ncoast.UUCP (Brandon Allbery) (10/23/87)

As quoted from <289@minya.UUCP> by jc@minya.UUCP (John Chambers):
+---------------
| Hi, folks.  Here's my shell puzzle of the day.  We all learn in our first
| hour of Unix lessons how to redirect input and output of any command that
| is started by a shell.  What I'd like to know is:  Is there a "right" way
| to tell the shell to redirect the output of ALL subsequent commands to a
| file?
+---------------

Nonintuitive, ugly, and while it's documented it took me years to figure
out that this was what they meant:

Start your script with "exec >file 2>&1".  (Note that you don't actually
exec anything, all you give are the redirections.)
-- 
Brandon S. Allbery		     necntc!ncoast!allbery@harvard.harvard.edu
  {{harvard,mit-eddie}!necntc,well!hoptoad,sun!mandrill!hal}!ncoast!allbery

ignatz@chinet.UUCP (Dave Ihnat) (10/24/87)

As many people have provided correct answers to the original redirection
query (i.e., to do something like "exec >fud 2>&1", I won't say it
here...

But nobody gave the fellow a little freebie that I don't see many
other people using; that is, you can open other files that way, too:

	exec 3>fred
	exec 4>charlie

Then, later, you can have specific output in the script go to these
files via, for instance,

	command >&4

Arcane, yes; but useful at times.  The biggest advantage is to open
one for input ("exec 4<foo"); subsequent "read INLINE <&4" will retain
their current positions in the file, unlike 'line'.  Note that you can
and *will* interact with any programs you're running in the script,
since you're opening file descriptors...
-- 
			Dave Ihnat
			ihnp4!homebru!ignatz || ihnp4!chinet!ignatz
			(w) (312) 882-4673