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

hello monks,
I've got a question, I have a lot of little scripts all based on a common perl package, all the scripts prints status messages on stdout and stderr. Now I want to redirect this output to a logfile with timestamps but I don't want to modify every print statement in each script. I need to filter the output to stdout and stderr, add a timestamp and write it to a logfile. I've read 'Filtering Your Own output' on the cookbook but I don't like to fork, because there will be too many scripts running.
I would like to know if there is a better solution (without forking) or if there is a package that does this for me,
Thanks in advance,
pix

Replies are listed 'Best First'.
Re: filtering my own output
by mirod (Canon) on Sep 06, 2001 at 18:43 UTC

    Hey, time to use my favourite trick: opening a pipe to a post-processor:

    #!/bin/perl -w use strict; my $log= "logfile"; open( STDOUT, "| perl -p -e 'print q{[}, scalar localtime() , q{] };' +>> $log" ) or die "cannot redirect output (open): $!"; print "Here he comes to save the day!\n"; # warning, if you don't have permission to write the file # then the open will succeed but the close will fail, # try it, it's quite surprising close STDOUT or die "cannot redirect output (close): $!";
Re: filtering my own output
by RhetTbull (Curate) on Sep 06, 2001 at 19:50 UTC
    I recommend Filter::Handle. I think it will do exactly what you want. I used it for the very same purpose -- to log the output a script without changing print statements, etc. Here's a sample script.
    #!/usr/local/bin/perl use warnings; use strict; use Filter::Handle qw/subs/; #open the logfile open (LOGFILE,">>test.log") || die "open: $!"; #set up a sub to filter our output #print @_ to LOGFILE then also print it to STDERR Filter \*STDERR, sub { local $_ = "@_"; print LOGFILE scalar(localtime), ": $_"; $_ +}; #test it out by printing something to STDERR print STDERR "hello world\n"; #turn off filtering UnFilter \*STDERR; close LOGFILE || die "close: $!";
    When run, this produces the following output:
    /home/rhet/misc> ./filter.pl hello world /home/rhet/misc> cat test.log Thu Sep 6 11:46:24 2001: hello world /home/rhet/misc>
Re: filtering my own output
by Chady (Priest) on Sep 06, 2001 at 18:21 UTC

    You can make a script that reads from STDIN and pipe the two together:

    perl script1.pl | perl log.pl

    The script log.pl reads the data spit out from script1.pl and does what it does with it.


    He who asks will be a fool for five minutes, but he who doesn't ask will remain a fool for life.

    Chady | http://chady.net/
Re: filtering my own output
by MZSanford (Curate) on Sep 06, 2001 at 18:17 UTC
    for redirecting, you could add something like open(STDOUT,">> logfile") at the top of the code ... but that does not add the time stamp. You could also write your own print() function, which checks to see if the File handle is given, and if it is not, verify the currently select()'d filehandle is stdout, and if both of those are met (meaning it was called like print "...";), you could attach a date/time and print to a log file. I do not suggest writing your own print funtion. Doing so would make your current code maintnence problem seem like a trip to YAPC
    can't sleep clowns will eat me
    -- MZSanford
Re: filtering my own output
by jlongino (Parson) on Sep 06, 2001 at 18:22 UTC
    This is almost exactly like a recent post. Just searching on "stderr redirect" matches many relevant nodes. Good luck.
    @a=split??,'just lose the ego and get involved!';
    for(split??,'afqtw{|~'){print $a[ord($_)-97]}