Insert standard disclaimer that, honest, I've tried to find the answer to this question on my own and haven't been able to find it.

This isn't your usual "How to I redirect STDERR?" question. I have a specific set of requirements that haven't been met by any of the techniques I can find. Those requirements are as follows:

  1. The technique captures STDERR from both Perl commands (e.g. print STDERR "whatever\n") and external commands (e.g. system 'ls file-that-does-not-exist.txt').
  2. STDERR is directed to a tied file handle. That handle does whatever it does with that data. The point here isn't what it does, just that the data gets sent to the handle.
  3. The life of the tied handle is associated with the life of an object. That object is referenced by one or more lexical variables. When the object goes out of scope then STDERR is returned to its previous state. This is not actually an absolute requirement, but it would be way prefered.
  4. The scope of the object might not be a single lexical scope, so solutions involving local probably won't work.
  5. I only care if it works in Un*x.
So, code might look something like this:
sub get_stderr {
   my ($capturer);
   $capturer = CAPTURE::Class->new();
   return $capturer;
}

# in some other file:
my $capturer = get_stderr();

# Run commands that might output to STDERR.
print STDERR "STDERR in perl\n";
system 'ls file-that-does-not-exist.txt';

# later...
undef $capturer;
print STDERR "stuff that doesn't go to capturer\n";
The closest I've been able to come is to capture STDERR, including stuff from external commands, like this:
#!/usr/bin/perl -w
use strict;

# redirect STDERR to a log file
open (STDERR, '>', './log.txt') or die "could not open STDERR: $!\n";

# print to STDERR in Perl
print STDERR "STDERR in perl\n";

# run an external command that outputs something to STDERR
system 'ls file-that-does-not-exist.txt';
That's nice as far as it goes, but it doesn't quite meet my needs. First, STDERR is only sent to a file. I can't figure out how to send it do a tied object. I have found ways to send STDERR to a tied object, but those techniques don't capture STDERR from external commands. Second, I can't figure out how to restore STDERR to its previous state once I'm done with the tied handle.

Much thanks, and looking forward to your help.


In reply to Capturing STDERR (this is not a FAQ) by mikosullivan

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.