Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I redirect STDOUT and STDERR to a log file in Perl? [duplicate]

Tags:

perl

Possible Duplicate:
Can I send STDOUT and STDERR to a log file and also to the screen in Win32 Perl?

I would to to redirect STDOUT, STDERR to temp_log and then to logfile.txt after the process is complete. The process runs for complete 20 minutes thus I would like to flock the temp_log in the time process runs.

like image 707
turbo111 Avatar asked Sep 29 '10 14:09

turbo111


2 Answers

STDOUT and STDERR are just filehandles that are initialized to your program's standard output and error, but they can be reassigned at any time for any reason. For this purpose, you will want to save the original settings so you can restore them.

sub process_that_writes_to_temp_log {

    # save original settings. You could also use lexical typeglobs.
    *OLD_STDOUT = *STDOUT;
    *OLD_STDERR = *STDERR;

    # reassign STDOUT, STDERR
    open my $log_fh, '>>', '/logdirectory/the-log-file';
    *STDOUT = $log_fh;
    *STDERR = $log_fh;

    # ... 
    # run some other code. STDOUT/STDERR are now redirected to log file
    # ...

    # done, restore STDOUT/STDERR
    *STDOUT = *OLD_STDOUT;
    *STDERR = *OLD_STDERR;
}

Depending on how your program is laid out, saving and restoring the old STDOUT/STDERR settings can be done automatically using local.

sub routine_that_writes_to_log {
    open my $log_fh, '>>', 'log-file';
    local *STDOUT = $log_fh;
    local *STDERR = $log_fh;

    # now STDOUT,STDERR write to log file until this subroutine ends.
    # ...

}
like image 137
mob Avatar answered Nov 04 '22 00:11

mob


The redirection part of your question is already answered in Can I send STDOUT and STDERR to a log file and also to the screen in Win32 Perl?. Even though it says "Win32", the answers are for portable Perl.

The other part, the temporary file, is a bit more tricky until you've been burned by it at least once.

  • Name the temporary file with something that should be unique during its run. Including the PID or the program start time. You can do that on your own with something like $filename.$$, but you can also use File::Temp.

  • If you want to then append the temporary log to an existing log, you probably want to make another temp file to get the entire result. Once you have the entire thing stitched together, move it into place. That way you don't have competing processes changing the same file as they all try to append their temp logs to the main one.

  • Even better, use something like Log::Log4perl since it handles all the details for you.

like image 25
brian d foy Avatar answered Nov 04 '22 00:11

brian d foy