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:
-
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').
-
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.
-
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.
-
The scope of the object might not be a single lexical scope, so solutions
involving local probably won't work.
-
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.