hkpatv has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to use TeeOutput to capture STDOUT to temporary file. I can get it to work with old stye, uppercase global filehandles, but cannot get it to work using proper filehandle variables.
#!/usr/bin/perl -w use Local::TeeOutput; use IO::File; use strict; local *LOG; open (LOG, ">>test.out"); openTee(*STDOUT, *STDOUT, *LOG); print "One\n"; closeTee(*STDOUT); my $fh = IO::File->new(">>test.out"); openTee(*STDOUT, *STDOUT, $fh); print "Two\n"; closeTee(*STDOUT);
Note that only "one" gets written to test.out. The documentation for TeeOutput states "The filehandle must be passed as an unquoted typeglob." I am not sure how to achieve that from a regular filehandle. (Note I actually want to store result in string variable but this is the first step) Any help appreciated.

Replies are listed 'Best First'.
Re: Problems with Filehandles and TeeOutput
by ikegami (Patriarch) on Aug 26, 2008 at 02:49 UTC

    Looking at the source, the inputs to openTee must be a glob (ref(\$file) eq 'GLOB'), a string expression starting with ">" or ">>", or a file name (opened for append).

    Based on some quick testing (without the module), all of these should work

    local *LOG; open(LOG, '>>test.out'); openTee(*STDOUT, *STDOUT, *LOG); my $fh = IO::File->new(">>test.out"); openTee(*STDOUT, *STDOUT, *$fh); open(my $fh, '>>', 'test.out'); openTee(*STDOUT, *STDOUT, *$fh); openTee(*STDOUT, *STDOUT, '>>test.out'); openTee(*STDOUT, *STDOUT, 'test.out');

    By the way, why do you want to use IO::File instead of open anyway?

      OK, here is the results of my testing:
      #Works local *LOG; open(LOG, '>>test.out'); openTee(*STDOUT, *STDOUT, *LOG); #Does not work my $fh = IO::File->new(">>test.out"); openTee(*STDOUT, *STDOUT, *$fh); #Does not work open(my $fh, '>>', 'test.out'); openTee(*STDOUT, *STDOUT, *$fh); #Does not work open(my $fh, '>>', 'test.out'); openTee(*STDOUT, *STDOUT, *$fh); #Works openTee(*STDOUT, *STDOUT, '>>test.out'); #Works openTee(*STDOUT, *STDOUT, 'test.out');
      Note the resason I am using IO::File is because actually I want to use IO::File->new_tmpfile, but as that doesn't work I am trying IO::File->new to make testing easier. Note the only reason I was trying to get new_tmpfile working was cause I couldn't get it into a string using scalar I/O
      open($fh, "+<", \$string);
        Sorry, but the module you are using wasn't written to work on lexical handles, introduced over 8 years ago with 5.6.

        Update: IO::Tee appears to work with lexical file handles as well.

        I couldn't help but notice that you used
        #Does not work open(my $fh, '>>', 'test.out'); openTee(*STDOUT, *STDOUT, *$fh);
        instead of
        #Should be working open(my $fh, '>>', 'test.out'); openTee(*STDOUT, *STDOUT, $fh); #asterisks ONLY before STDOUT, NOT $fh
        would you mind testing once more?
        []s, HTH, Massa (κς,πμ,πλ)
Re: Problems with Filehandles and TeeOutput
by massa (Hermit) on Aug 26, 2008 at 02:25 UTC
    Your $fh variable is not a regular filehandle, but an IO::File instance. Try
    open my $fh, '>>', 'test.out';
    in your second example and tell us what happens. (I don't have TeeOutput installed to test...)
    []s, HTH, Massa (κς,πμ,πλ)
Re: Problems with Filehandles and TeeOutput
by apl (Monsignor) on Aug 26, 2008 at 10:52 UTC
    You might also want to consider testing the success of your open before going on. That is, replace
    open (LOG, ">>test.out");
    with
    open (LOG, ">>test.out") or die "Failed to open test.out: $!";