[clug] Next in my series of "how to do things in /bin/sh that you probably shouldn't".
sjenkin at canb.auug.org.au
Wed Aug 19 21:39:39 MDT 2009
Andrew Janke wrote on 20/8/09 10:39 AM:
> Suppose that I want to send all output from a shell script to a
> logfile as well as displaying it (within the script). To simply send
> everything in a shell script I can just do this somewhere near the top
> of the script:
> exec > logfile.txt 2>&1
> But I am greedy, as such it is a pity you can't just do this:
> exec | tee logfile 2>&1
> So instead the only way I know of doing this is as such:
<snip> Example using a named pipe.
> Seems like an awful amount of work for a simple thing, anyone know a
> better way? Answers of "use python/perl/<some other language>" will
> be dutifully ignored.
> Andrew Janke
> (a.janke at gmail.com || http://a.janke.googlepages.com/)
> Canberra->Australia +61 (402) 700 883
Great question. Thanks for that.
I've spent a little time playing with this - it seems like a nice thing
to do - and think I've spotted the root cause, which points to the
It's to do with shell creating 'pipes' and fiddling per-process file
When you run:
cmd1 | cmd 2
shell does this work for you:
for '|': call pipe() and save pipe_fd and pipe_fd
cmd1: leave fd & fd alone.
close fd, dup pipe_fd to fd
now fork & exec 'cmd1'
cmd2: leave fd & fd alone.
close fd, dup pipe_fd to fd
now fork & exec 'cmd2'
Wait for completion of both processes...
Return in "$?" the status of cmd2, ignore cmd1's ret-code.
[I could've reversed the sense of the fd's from pipe()]
IIRC, /bin/sh, spawns processes Right to Left, just an added wrinkle.
The essence of the problem is creating the pipe() and associated array
There are some very smart people on this list (you know who you are) who
know much shell trickery. Perhaps they know of a way to capture a 'pipe'
and the file-descriptors at each end of it.
As in, create two processes with a pipe between them & capture the
fd's, then reuse when the processes have exited.
Seems hard because of the local context of each process and passing
I've never investigated 'csh' and descendants in detail - it may have
facilities to allow pipe & fd fiddling.
OR, doing it simply in 'standard shell' is possible only in two ways:
- create a named pipe and manipulate fd's & child processes (your soln)
- use a wrapper to get shell to automagically do the work.
AND, I could be completely wrong headed and Missed The Bleeding Obvious.
Happened before, will happen again :-)
Now, if the semantics of pipes and sockets were more similar, this might
be a little different.
Remember how Tridge solved the 'shell as IP daemon' problem by *writing*
to the socket given as stdin?
Took me by surprise & impressed the hell out me :-)
Looking forward to the continued conversation on this.
Steve Jenkin, Info Tech, Systems and Design Specialist.
0412 786 915 (+61 412 786 915)
PO Box 48, Kippax ACT 2615, AUSTRALIA
sjenkin at canb.auug.org.au http://members.tip.net.au/~sjenkin
More information about the linux