>>>>> "BT" == Ben Tilly <[EMAIL PROTECTED]> writes:
BT> On 5/9/05, Uri Guttman <[EMAIL PROTECTED]> wrote: >> >>>>> "BT" == Ben Tilly <[EMAIL PROTECTED]> writes: >> BT> Be aware that IO::Tee has limitations. It only works for output that BT> goes through Perl's IO system. In particular if your program makes BT> a system call, the child process will NOT see the tee. >> >> i bet you can work around that by saving STDOUT, reopening it on IO::Tee >> and having IO::Tee output to the file and the saved STDOUT. i leave >> implementing this as an exercise to the reader. but using shell to do >> this is probably the easiest as you can just use tee and all stdout >> piped to it (from the perl program or its subprocesses) will get >> teed. as larry says, the shell has to be useful for something! BT> You'd lose that bet. i am not sure about that. it might need some hacking to do it. BT> IO::Tee is implemented through tying a filehandle inside of Perl. BT> The entire mechanism only makes sense from within Perl. A BT> launched subprocess (or poorly written XS code) goes through a BT> fileno that the operating system knows about. Since the OS does BT> not know about Perl's abstractions of I/O, there is no way to get BT> the OS to direct output through them. you can then do the STDOUT dup stuff yourself and then bind IO::Tee to that. by closing STDOUT and reopening it to a pipe you create, all the children process will output to that pipe since they will see it as fd 0. you have to fork and have that read the other side of the pipe and use IO::Tee in there. like i said, not simple but doable. this is effectively what the shell does when you pipe anyway. another totally different approach is to use one of my perl sayings, print rarely, print late. too much code is written with direct calls to print (with or without explicit handles). when you print late, you just build up all your output in strings with .= and then just return it to the caller. only at the highest level where the actual print decisions are really made do you finally call print. this is also faster as print is very slow as it invokes all manner of stdio/perlio code each time it is called. appending to a buffer is very fast and clean. so if you did it this way, the top level would be like: use File::Slurp ; my $text = do_lots_of_work_and_return_all_the_text() ; print $text ; write_file( $tee_file, $text ) if $tee_file ; it makes for a very good api too in all the other subs. most just return text and don't do any output themselves. then you can use the subs in any way you want, for output, sending a message, log entries, etc. printing at the point of text generation makes this impossible. as for subprocesses, you just use backticks instead of system and collect the output. the one downside is when you need output to be flushed such as when you are working with pipes. this can be handled too by just calling syswrite at the proper places and having the lower level subs return text as before. isolating content generation from its destination is a good design idea that isn't used enough. uri -- Uri Guttman ------ [EMAIL PROTECTED] -------- http://www.stemsystems.com --Perl Consulting, Stem Development, Systems Architecture, Design and Coding- Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org _______________________________________________ Boston-pm mailing list Boston-pm@mail.pm.org http://mail.pm.org/mailman/listinfo/boston-pm