]> Frank Brehm's Git Trees - scripts/solaris.git/commitdiff
Bis zur Ermittlung der alten Logdateien gekommen
authorFrank Brehm <frank@brehm-online.com>
Tue, 28 Mar 2006 16:56:19 +0000 (16:56 +0000)
committerFrank Brehm <frank@brehm-online.com>
Tue, 28 Mar 2006 16:56:19 +0000 (16:56 +0000)
LogRotate.pm

index d317de275455ddc2f50b76473c0a47e0b8ac6702..b8ac3f0e363998fed375837f20a5809484ff483d 100644 (file)
@@ -160,6 +160,191 @@ sub check_state($) {
 
 }
 
+#------------------------------------------------------------------------------------------
+    
+=head2 collect_old_logfiles( $file )
+
+Ermittelt alle alten, bisher rotierten Logdateien zu der uebergebenen Logdatei und gibt diese
+als Hash-Ref mit den Dateinamen als Key und dem Zeitstempel der letzten Aenderung als Wert zurueck.
+
+=cut
+
+sub collect_old_logfiles($$) {
+
+  my $self = shift;
+  my $file = shift;
+  my $p = verbose() ? __PACKAGE__ . "::collect_old_logfiles(): " : "";
+
+  my ( $dir, $basename, $olddir, $pattern, $t );
+  my ( @Pattern, @Liste, @Stats );
+
+  my $ce = $self->{'c'}->compressext();
+  if ( not defined($ce) or $ce =~ /^\s*$/ ) {
+    $ce = ".gz";
+  }
+  $ce = "." . $ce if $ce ne "" and $ce !~ /^\./;
+  print $p . "Kompressionsendung '$ce'.\n" if verbose() > 3;
+
+  unless ( $file ) {
+    carp( $p . "Keine Logdatei uebergeben!\n" );
+    return undef;
+  }
+  print $p . "Ermittle alten Logdateien fuer '$file'.\n" if verbose();
+  my $f = $self->{'c'}{'logfiles'}{$file};
+
+  my $ext = defined $f->{'extension'} ? $f->{'extension'} : "";
+  $ext = "" if $ext =~ /^\s*$/;
+  $ext = "." . $ext if $ext ne "" and $ext !~ /^\./;
+  my $ext_ohne = $ext;
+
+  # Compress-Endung hinten dran bammeln ...
+  if ( $f->{'compress'} ) {
+    my $ce = $self->{'c'}->compressext();
+    if ( not defined($ce) or $ce =~ /^\s*$/ ) {
+      $ce = ".gz";
+    }
+    $ce = "." . $ce if $ce ne "" and $ce !~ /^\./;
+    $ext .= $ce;
+  }
+
+  my $res = {};
+
+  unless ( ( $dir, $basename ) = $file =~ m#(.*)/([^/]*)$# ) {
+    warn $p . "Ungueltiger Logdateiname: '$file'\n";
+    return undef;
+  }
+
+  if ( $f->{'dateext'} ) {
+    $basename .= ".*";
+  }
+
+  if ( $f->{'olddir'} and $f->{'olddir'}{'dirname'} ) {
+
+    # Ersetzung aller Platzhalter in Olddir-Angabe
+
+    $olddir = $f->{'olddir'}{'dirname'};
+
+    # Verzeichnisname ...
+    $olddir =~ s/(?:\${dirname}|\$dirname(?![a-zA-Z0-9_]))/$dir/g;
+
+    # Basename ...
+    $olddir =~ s/(?:\${basename}|\$basename(?![a-zA-Z0-9_]))/$basename/g;
+
+    # Nodename
+    $t = $self->{'template'}{'nodename'};
+    $olddir =~ s/(?:\${nodename}|\$nodename(?![a-zA-Z0-9_]))/$t/g;
+
+    # Domain
+    $t = $self->{'template'}{'domain'};
+    $olddir =~ s/(?:\${domain}|\$domain(?![a-zA-Z0-9_]))/$t/g;
+
+    # Platform
+    $t = $self->{'template'}{'platform'};
+    $olddir =~ s/(?:\${platform}|\$platform(?![a-zA-Z0-9_]))/$t/g;
+
+    # Isa
+    $t = $self->{'template'}{'isa'};
+    $olddir =~ s/(?:\${isa}|\$isa(?![a-zA-Z0-9_]))/$t/g;
+
+    # Release
+    $t = $self->{'template'}{'release'};
+    $olddir =~ s/(?:\${release}|\$release(?![a-zA-Z0-9_]))/$t/g;
+
+    # Machine
+    $t = $self->{'template'}{'machine'};
+    $olddir =~ s/(?:\${machine}|\$machine(?![a-zA-Z0-9_]))/$t/g;
+
+    $olddir = $dir . "/" . $olddir unless $olddir =~ m#^/#;
+
+    # Ersetzen aller POSIX::strftime-Platzhalter durch Shell-Pattern:
+    # Wochentag
+    $olddir =~ s/\%a/*/gi;
+    # Monatsname
+    $olddir =~ s/\%b/*/gi;
+    $olddir =~ s/\%h/*/g;
+    # Datum komplett
+    $olddir =~ s/\%c/*/g;
+    # Jahrhundert
+    $olddir =~ s/\%C/[0-9][0-9]/g;
+    # Tag im Monat
+    $olddir =~ s/\%d/[0-9][0-9]/g;
+    # Datum als %m/%d/%y
+    $olddir =~ s#\%D#[0-9][0-9]/[0-9][0-9]/[0-9][0-9]#g;
+    $olddir =~ s#\%x#[0-9][0-9]/[0-9][0-9]/[0-9][0-9]#g;
+    # Stunde im 24h-Format
+    $olddir =~ s/\%H/[012][0-9]/g;
+    # Stunde im 12h-Format
+    $olddir =~ s/\%J/[01][0-9]/g;
+    # Nummer des Tags im Jahr
+    $olddir =~ s/\%j/[0123][0-9][0-9]/g;
+    # Stunde im 24h-Format
+    $olddir =~ s/\%k/[\\ 12][0-9]/g;
+    # Stunde im 12h-Format
+    $olddir =~ s/\%l/[\\ 1][0-9]/g;
+    # Monatsnummer
+    $olddir =~ s/\%m/[0-9][0-9]/g;
+    # Minute
+    $olddir =~ s/\%M/[0-5][0-9]/g;
+    # AM/PM
+    $olddir =~ s/\%p/[AP]M/g;
+    # komplette Uhrzeit im 12h-Format mit AM/PM
+    $olddir =~ s/\%r/[01][0-9]:[0-5][0-9]:[0-5][0-9] [AP]M/g;
+    # Uhrzeit im Format %H:%M
+    $olddir =~ s/\%R/[012][0-9]:[0-5][0-9]/g;
+    # Sekunden
+    $olddir =~ s/\%S/[0-6][0-9]/g;
+    # komplette Uhrzeit im 24h-Format
+    $olddir =~ s/\%T/[012][0-9]:[0-5][0-9]:[0-5][0-9]/g;
+    $olddir =~ s/\%X/[012][0-9]:[0-5][0-9]:[0-5][0-9]/g;
+    # Wochentag als Zahl (1-7)
+    $olddir =~ s/\%u/[0-7]/g;
+    $olddir =~ s/\%w/[0-7]/g;
+    # Nummer der Woche im Jahr
+    $olddir =~ s/\%U/[0-5][0-9]/g;
+    $olddir =~ s/\%V/[0-5][0-9]/g;
+    $olddir =~ s/\%W/[0-5][0-9]/g;
+    # Jahr
+    $olddir =~ s/\%Y/[1-9][0-9][0-9][0-9]/g;
+    # Zeitzone
+    $olddir =~ s/\%Z/*/g;
+
+  } else {
+
+    $olddir = $dir;
+
+  }
+
+  push @Pattern, $olddir . "/" . $basename . $ext;
+  push @Pattern, $olddir . "/" . $basename . ".[0-9]" . $ext;
+  push @Pattern, $olddir . "/" . $basename . ".[0-9][0-9]" . $ext;
+  push @Pattern, $olddir . "/" . $basename . ".[0-9][0-9][0-9]" . $ext;
+  push @Pattern, $olddir . "/" . $basename . ".[0-9][0-9][0-9][0-9]" . $ext;
+  if ( $f->{'compress'} ) {
+    push @Pattern, $olddir . "/" . $basename . $ext_ohne;
+    push @Pattern, $olddir . "/" . $basename . ".[0-9]" . $ext_ohne;
+    push @Pattern, $olddir . "/" . $basename . ".[0-9][0-9]" . $ext_ohne;
+    push @Pattern, $olddir . "/" . $basename . ".[0-9][0-9][0-9]" . $ext_ohne;
+    push @Pattern, $olddir . "/" . $basename . ".[0-9][0-9][0-9][0-9]" . $ext_ohne;
+  }
+
+#  $pattern = '"' . join( '" "', @Pattern ) . '"';
+#  print $p . "Suchpattern nach den alten Logdateien: '$pattern'.\n" if verbose() > 2;
+
+#  @Liste = glob( $pattern );
+
+  foreach $pattern ( @Pattern ) {
+    print $p . "Suche nach Pattern '$pattern'.\n" if verbose() > 2;
+    @Liste = glob( $pattern );
+    for ( @Liste ) {
+      print "    - '$_'\n" if verbose() > 3;
+      @Stats = stat $_;
+      $res->{$_} = $Stats[9];
+    }
+  }
+
+  return $res;
+}
+
 #------------------------------------------------------------------------------------
 
 =head2 create_olddir ( $logfile )
@@ -409,9 +594,11 @@ sub find_rotatings($$$) {
     $t_new = $target . "." . $i . $ext;
     $t_new_ohne = $target . "." . $i . $ext_ohne;
     print $p . "Zyklische Rotation '$t_ohne' -> '$t_new_ohne'.\n" if verbose() > 3;
-    $pair = { 'from' => $t_ohne,
-              'to'   => $t_new_ohne,
+    $pair = { 'from'       => $t_ohne,
+              'to'         => $t_new_ohne,
+              'compressed' => 0,
             };
+    $pair->{'compressed'} = 1 if -f $t and $f->{'compress'};
     unshift @{$res->{'move'}}, $pair;
     $t = $t_new;
     $t_ohne = $t_new_ohne;
@@ -652,14 +839,16 @@ sub rotate_file($$) {
   my $file = shift;
   my $p = verbose() ? __PACKAGE__ . "::rotate_file(): " : "";
 
-  #my ( $dir, $adir, $mode, $owner, $group, $olddir );
-  #my ( $pmode, $puid, $pgid );
-  #my ( @Dirs, @Stats );
+  my ( $target, $rotates, $pair, $from, $to );
+  my ( $omode, $ouid, $ogid, $nmode, $nuid, $ngid, $atime, $mtime );
+  my ( @Stats );
 
-  my ( $target, $rotates );
-
-  my $uid      = $>;
-  my ( $gid )  = $) =~ /^(\d+)/;
+  my $ce = $self->{'c'}->compressext();
+  if ( not defined($ce) or $ce =~ /^\s*$/ ) {
+    $ce = ".gz";
+  }
+  $ce = "." . $ce if $ce ne "" and $ce !~ /^\./;
+  print $p . "Kompressionsendung '$ce'.\n" if verbose() > 2;
 
   unless ( $file ) {
     carp( $p . "Keine Logdatei uebergeben!\n" );
@@ -687,8 +876,142 @@ sub rotate_file($$) {
 
   print $p . "Ermittelte Moves: " . Dumper($rotates) if verbose() > 2;
 
+  # Zuerst mal alles Alte zyklisch rotieren ...
+  
+  for $pair ( @{$rotates->{'move'}} ) {
+    $from = $pair->{'from'};
+    $to   = $pair->{'to'};
+    if ( $pair->{'compressed'} ) {
+      $from .= $ce;
+      $to   .= $ce;
+    }
+    print $p . "Umbenennung '$from' => '$to'.\n";
+    unless ( $self->{'test'} ) {
+      unless ( move $from, $to ) {
+        warn $p . "Konnte '$from' nicht in '$to' umbenennen: $!\n";
+        return undef;
+      }
+    }
+  }
+
+  # Jetzt die eigentliche Rotation ...
+
+  $from = $rotates->{'rotate'}{'from'};
+  $to   = $rotates->{'rotate'}{'to'};
+
+  $f->{'rotated'} = $to;
+
+  if ( $f->{'copytruncate'} ) {
 
+    # alte Permissions und Besitzer der rotierten Datei ermitteln
+    @Stats = stat $from;
+    ( $omode, $ouid, $ogid, $atime, $mtime ) = @Stats[ 2, 4, 5, 8, 9 ];
 
+    print $p . "Kopiere '$from' nach '$to' ...\n";
+    unless ( $self->{'test'} ) {
+      unless ( copy $from, $to ) {
+        warn $p . "Konnte '$from' nicht nach '$to' kopieren: $!\n";
+        return undef;
+      }
+    }
+
+    print $p . "Trunce Datei '$from' ...\n";
+    unless ( $self->{'test'} ) {
+      if ( open FILE, ">$from" ) {
+        close FILE;
+      } else {
+        warn $p . "Konnte Logdatei '$from' nicht truncen: $!\n";
+        return undef;
+      }
+    }
+
+    # gewünschte Permissions setzen
+    print $p . "Setze Permissions von '$to'.\n" if verbose();
+    unless ( $self->{'test'} ) {
+      unless ( chmod $omode, $to ) {
+        warn $p . "Setzen der Permissions von '$to' war nnicht erfolgreich: $!\n";
+      }
+    }
+    
+    # gewünschte Besitzer stzen
+    print $p . "Setze Besitzer von '$to'.\n" if verbose();
+    unless ( $self->{'test'} ) {
+      unless ( chown $ouid, $ogid, $to ) {
+        warn $p . "Setzen des Besitzers von '$to' war nicht erfolgreich: $!\n";
+      }
+    }
+
+    # Access- und Modification-Time setzen ...
+    print $p . "Setze Access- und Modification-Time von '$to'.\n" if verbose();
+    unless ( $self->{'test'} ) {
+      unless ( utime $atime, $mtime, $to ) {
+        warn $p . "Setzen der Access- und Modification-Time von '$to' war nicht erfolgreich: $!\n";
+      }
+    }
+
+  } else {
+
+    print $p . "Benenne um bzw. verschiebe '$from' nach '$to' ...\n";
+    unless ( $self->{'test'} ) {
+      unless ( move $from, $to ) {
+        warn $p . "Konnte '$from' nicht nach '$to' umbenennen/verschieben: $!\n";
+        return undef;
+      }
+    }
+
+    if ( $f->{'create'} ) {
+
+      print $p . "Lege '$from' neu an ...\n";
+      unless ( $self->{'test'} ) {
+        if ( open FILE, ">$from" ) {
+          close FILE;
+        } else {
+          warn $p . "Konnte Logdatei '$from' nicht neu anlegen: $!\n";
+          return undef;
+        }
+      }
+
+      # alte Permissions und Besitzer der neu angelegten Datei ermitteln
+      @Stats = stat $from;
+
+      ( $omode, $ouid, $ogid ) = @Stats[ 2, 4, 5 ];
+      # gewünschte Permissions und Besitzer ermittel
+      $nmode = $f->{'create'}{'mode'} || 0644;
+      $nuid  = $f->{'create'}{'owner'};
+      $ngid  = $f->{'create'}{'group'};
+
+      if ( $nmode != $omode ) {
+        # gewünschte Permissions setzen
+        print $p . "Setze Permissions von '$from'.\n" if verbose();
+        unless ( $self->{'test'} ) {
+          unless ( chmod $nmode, $from ) {
+            warn $p . "Setzen der Permissions von '$from' war nnicht erfolgreich: $!\n";
+          }
+        }
+      }
+
+      if ( $ouid != $nuid or $ogid != $ngid    ) {
+        # gewünschte Besitzer stzen
+        print $p . "Setze Besitzer von '$from'.\n" if verbose();
+        unless ( $self->{'test'} ) {
+          unless ( chown $nuid, $ngid, $from ) {
+            warn $p . "Setzen des Besitzers von '$from' war nicht erfolgreich: $!\n";
+          }
+        }
+      }
+
+    }
+
+  }
+
+  # Ermittlung aller bisherigen Logfiles ...
+  my $old_logfiles = $self->collect_old_logfiles( $file );
+  unless ( $old_logfiles ) {
+    warn $p . "Fehler beim Ermitteln der bisher rotierten Logfiles.\n";
+    return undef;
+  }
+  print $p . "Liste aller bisher rotierten Logfiles: " . Dumper($old_logfiles) if verbose() > 1;
+  $f->{'oldfiles'} = $old_logfiles;
 
   return 1;