views:

560

answers:

3

In Unix, I need to be able to archive log files into monthly folders, labelled accordingly. How do I do this in Perl?

+2  A: 

When I have had this task, I use cronolog.

The package includes a Perl script called cronosplit that you can use to split an existing monolithic log file into %Y/%m/%d subdirectories.

Cronolog itself is a binary written in C that can be used as a piped target for logging. For example, you can use it in an Apache httpd.conf:

CustomLog "|/usr/sbin/cronolog /web/logs/%Y/%m/%d/access.log"
Bill Karwin
+4  A: 

Does it have to be Perl? Have you tried logrotate?

As far as a Perl solution: mkdir will create the directories, and if you use POSIX 'strftime';, then you'll be able to generate nice directory names based on the current time (ie, my $dirname = strftime('%Y-%m-%d',localtime()) will generate a YYYY-MM-DD string), and you can move the files using rename. That's just core Perl, there are a ton of CPAN modules that do some or all of this (such as File::Copy, instead of rename).

Andrew Barnett
+2  A: 

Let's provide an actual Perl idea, since that's what was asked for:

use File::Path qw<mkpath>;
use File::Spec;
use POSIX qw<strftime>;
use Smart::Comments;

my $directory 
    = File::Spec->catfile( $BASE_LOG_DIRECTORY
                         , strftime( "%Y-%B", localtime ) #2009-January
    );
### $directory
unless ( -e $directory ) {
    mkpath( $directory, { verbose => 1 } );
}
my $log_file_path = File::Spec->catfile( $directory, 'system.log' );
### $log_file_path

Output is

### $directory: '/my/base/directory/2009-January'
### $log_file_path: '/my/base/directory/2009-January/system.log'

Notes

  1. Install Smart::Comments, or comment it out.
  2. The constant $BASE_LOG_DIRECTORY is written in Readonly/PBP style
  3. Everything else should just come with Perl.
Axeman