This is the result of 10 minutes of pounding on the keyboard after yet another disappointing experience with trying to get logrotate to do something vaguely more flexible.
This simple script scans all normal files in a log directory, and if they are older than a certain cutoff, moves them into a holding directory for old logs. Future passes will check files in the old directory for another age setting and will delete them. That's all there is to it.
Configure your cutoffs, directories of interest, and optionally plug in a better logging mechanism and you're set. (Oh, and change the #! if necessary, of course).
<?
$cutoff_rotate = "3 days";
$cutoff_delete = "7 days";
$dir_log = "/logs";
$dir_old = "/logs.old";
function trace( $msg, $debug = FALSE ) {
// appropriate logging mechanism can be plugged in here
echo "[] $msg\n";
}
// scan old files for deletion
if( is_dir($dir_old) ) {
$dh = opendir( $dir_old );
if( $dh !== FALSE ) {
chdir( $dir_old );
trace( "scanning $dir_old for logs more than $cutoff_delete old" );
$cutoff = strtotime( "-$cutoff_delete" );
trace( "cutoff is ".date('r',$cutoff) );
while( ($file = readdir($dh)) !== FALSE ) {
if( is_dir($file) ) {
trace( "skipping $file", true );
continue;
} else {
$ts = filemtime($file);
if( $ts <$cutoff ) {
trace( "deleting $file, ".date('r',$ts) );
$succ = @unlink($file);
if( !$succ )
trace( "failed to unlink $file!" );
} else {
trace( "ignoring $file, ".date('r',$ts), true );
}
}
}
}
closedir( $dh );
} else {
trace( "no old log dir $dir_old to scan yet" );
}
// scan current files for rotation
if( file_exists($dir_old) ) {
trace( "creating $dir_old" );
$succ = @mkdir( $dir_old, 0775, true );
if( !$succ ) {
trace( "mkdir failed, aborting rotation" );
exit( 1 );
}
}
if( is_dir($dir_log) ) {
$dh = opendir( $dir_log );
if( $dh !== FALSE ) {
chdir( $dir_log );
trace( "scanning $dir_log for logs more than $cutoff_rotate old" );
$cutoff = strtotime( "-$cutoff_delete" );
trace( "cutoff is ".date('r',$cutoff) );
while( ($file = readdir($dh)) !== FALSE ) {
if( is_dir($file) ) {
trace( "skipping $file", true );
continue;
} else {
$ts = filemtime($file);
if( $ts <$cutoff ) {
trace( "rotating $file, ".date('r',$ts), true );
$succ = @rename( $file, $dir_old );
if( !$succ )
trace( "failed to rotate $file!" );
} else {
trace( "ignoring $file, ".date('r',$ts), true );
}
}
}
}
closedir( $dh );
}
?>
Nice script Ammon! I'll throw this into my toolbag. -A
[...] response to my two-step rotation post earlier this week, I figure I may as well share the logic I use for a more traditional logfile [...]