First off, for the case of catching STDERR when running another program, check out IPC::Open3, which has been in the standard perl distribution for years.
In the case of running other perl code and capturing the standard error output from it, say your second case above, you can do something like this in perl 5.8 and higher:
open my $savederr, '>&', \*STDERR;
my $module_stderr = '';
open(STDERR, '>', \$module_stderr);
SomeFunkyModule::sub_that_spews_to_stderr();
open(STDERR, '>&', $savederr);
# process the stuff in $module_stderr
In older perls, you can do the same thing with IO::String.
--
@/=map{[/./g]}qw/.h_nJ Xapou cets krht ele_ r_ra/;
map{y/X_/\n /;print}map{pop@$_}@/for@/
| [reply] [d/l] [select] |
First off, for the case of catching STDERR when running another program, check out IPC::Open3, which has been in the standard perl distribution for years.
Right, but this is not apropos to my question. By the way, whenever I think of IPC::Open3, I think instead of IPC::Run which is a much more tractable solution to the same problem set IMO</preaching>
As for your proposed solution. It almost works. I n order for STDERR to be effectively repointed to $module_stderr you have to explicitly close the filehandle and then reopen it. (this is a special requirement that only applies to STDOUT and STDERR when being repointed to an in-memory file). After adding this it does appear that STDERR is in fact repointed somewhere, but it's not clear to me where. It certainly isn't going into that in-memory file variable ($module_stderr). However, if you repoint STDERR to a real file rather than one of these funky in-memory file scalars, then the stderr does in fact end up in that file. Here is an example script which demonstrates the difference
my $module_stderr = '';
close STDERR;
open(STDERR, '>', \$module_stderr);
open F, "perl -e \"warn 'hi'\" |" or die "$!";
while( <F>) {
print 'out -> '.$_."\n";
}
close F;
print "err -> ". $module_stderr;
print "\n";
open(STDERR, '>', 'testfile') or die "$!";
open F, "perl -e \"warn 'hi'\" |" or die "$!";
while( <F>) {
print 'out -> '.$_."\n";
}
close F;
close STDERR;
print "err -> ". `cat testfile`;
The output I get on my setup (Windows XP, ActivePerl 5.8.7) is:
err ->
err -> hi at -e line 1.
I'm not sure where the standard err out is going in the first case; it's not in the variable and it doesn't show up in the normal terminal output either. Maybe it's just going to /dev/null or somewhere else in the ether.
Now if I could just figure out a way to get this to work without using a temporary file, I'd be a happy camper...
--DrWhy
"If God had meant for us to think for ourselves he would have given us brains. Oh, wait..."
| [reply] [d/l] [select] |
| [reply] [d/l] [select] |
Yes. The easiest is to open STDERR to some file before opening the "piped open". You could then read the file afterwards.
see perldoc -f open...
s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
+.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e
| [reply] [d/l] [select] |
You might also want to check out IPC::Run3, which handles this kind of thing fairly elegantly.
-xdg
Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.
| [reply] |