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

IF i redirect stderr to stdout in a ksh script the output is not interleafed as it happens but rather appears to come in chunks (buffered from separate buffers). How can I get perl to output stdout and stderr to the same output file as they happen - would make debugging so much easier, e.g.,

 script.pl > script.out 2>script.out

would result in output like

error1 error2 error3 abc def ghi

What i want is

abc def error1 error2 ghi error3

where error1 and error2 occur after def and before ghi, and error3 after ghi, and the errors are perl generated errors

Thanks

Replies are listed 'Best First'.
Re: interleaf stdout stderr to a file
by BrowserUk (Patriarch) on Mar 03, 2015 at 02:57 UTC

    You can redirect stdout to stderr within your program using BEGIN{ open STDOUT, '>&STDERR' }; then both will come out interleaved via the unbuffered stderr; and you only need 2>file in order to put everything in a file:

    E:\primes>perl -Mstrict -wE"BEGIN{ open STDOUT, '>&STDERR';} say 'hi'; + warn 1; say 'this is fun'; warn 2; say 'bye'" 2>log C:\test>type log hi 1 at -e line 1. this is fun 2 at -e line 1. bye

    Note: I think that if you do this at the top of your main script, before you use any modules, their output will also be redirected, but I didn't create a module with warnings to try it.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I'm with torvalds on this
    In the absence of evidence, opinion is indistinguishable from prejudice. Agile (and TDD) debunked
      an interesting solution. did not know stderr was unbuffered by default as looking at the output i originally had it looked to be buffered. thanks...
Re: interleaf stdout stderr to a file
by kennethk (Abbot) on Mar 03, 2015 at 00:42 UTC
    You should be able to accomplish this using select and the special variable $| to turn off buffering:
    select(STDERR); $| = 1; select(STDOUT); $| = 1;
    Of course, you'll likely have trouble if you execute your command as listed above, since the channels will clobber each other. You probably mean
    script.pl > script.out 2>&1

    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

      thanks this worked great!