Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses

duplicating STDERR to a logfile...

by cadphile (Beadle)
on May 08, 2002 at 21:52 UTC ( #165195=perlquestion: print w/replies, xml ) Need Help??

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

A simple question really: I want to capture the STDERR from commands like croak and cluck into a log file that records all output of my program. I've read the previous comments in Perl Monks and I find the following in the Camel book:
use FileHandle; use Carp qw (cluck croak); my $LOG_FH = new FileHandle( "somefile", "w" ); my $fileno = fileno $LOG_FH; open STDERR, ">&$fileno" or croak "Can't dup STDERR."; cluck "Testing the output of Carp commands.";
(I need to use the $fileno because the ">&" dup operation doesn't work on I/O typeglobs.)

This works fine: all STDERR after this goes into $LOG_FH, but it no longer goes to the terminal.

But what I want is like the command "tee". I want STDERR to go to the terminal window, AND to be duplicated into the $LOG_FH filehandle.

Any clues??

Thanks, -Cadphile

Replies are listed 'Best First'.
Re: duplicating STDERR to a logfile...
by Kanji (Parson) on May 08, 2002 at 21:54 UTC
(RhetTbull) Re: duplicating STDERR to a logfile...
by RhetTbull (Curate) on May 09, 2002 at 02:03 UTC
    My favorite way to handle this is with Filter::Handle. For example:
    use warnings; use strict; use Carp; use Filter::Handle qw/subs/; open (LOGFILE, ">logfile") or die "could not open logfile: $!"; #filter STDERR through an anonymous sub Filter \*STDERR, sub {local $_ = "@_"; print LOGFILE "Filtered: $_ "; +$_}; #need a signal handler to capture warnings from carp and warn which ar +e not captured by Filter::Handle (but by capturing ourselves and prin +ting to STDERR, they do get picked up by Filter::Handle) $SIG{__WARN__} = sub {local $_ = "@_"; print STDERR $_}; #prints to both STDERR and to LOGFILE print STDERR "error!\n"; carp "carp!"; warn "warn!"; #STDERR will no longer be filtered through your sub UnFilter \*STDERR; print STDERR "not captured to log\n"; warn "this one got away"; close LOGFILE;
    Update: Added signal handler to capture output of warn and carp
      Thanks RhetTbull -- This is the exact solution I was hunting for. Simple implementation, and it works just right.



Re: duplicating STDERR to a logfile...
by jsegal (Friar) on May 08, 2002 at 22:09 UTC
    How about (at least on UNIX)
    open(STDERR,"|tee somefile 1>&2"); print STDERR "this goes to STDERR and somefile\n";
    (The "1>2" ensures that what gets printed still goes to your main process's STDERR instead of STDOUT).

Re: duplicating STDERR to a logfile...
by belg4mit (Prior) on May 09, 2002 at 01:42 UTC
    Another means would be to install a signal handler, this would receive Carp's cooked messages and you could tee from within. I wouldn't recommend opening the file within the handler though (memory allocaiton and (un)safe signal handling).

    Alternatively you could just use Carp::longmess and Carp::shortmess yourself.

    perl -pew "s/\b;([mnst])/'$1/g"

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://165195]
Approved by Kanji
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (8)
As of 2020-01-23 16:17 GMT
Find Nodes?
    Voting Booth?