]> Frank Brehm's Git Trees - scripts/solaris.git/commitdiff
Neu dazu
authorFrank Brehm <frank@brehm-online.com>
Tue, 21 Mar 2006 17:54:32 +0000 (17:54 +0000)
committerFrank Brehm <frank@brehm-online.com>
Tue, 21 Mar 2006 17:54:32 +0000 (17:54 +0000)
LogRotate/StateFile.pm [new file with mode: 0644]

diff --git a/LogRotate/StateFile.pm b/LogRotate/StateFile.pm
new file mode 100644 (file)
index 0000000..2f1bbc0
--- /dev/null
@@ -0,0 +1,362 @@
+package LogRotate::StateFile;
+
+# $Id$
+# $URL$
+
+=head1 NAME
+
+B<LogRotate/StateFile.pm> - Logrotate Statusdatei Modul
+
+=head1 SYNOPSIS
+
+  my $statefile = new LogRotate::StateFile();
+
+  $statefile->verbose(2);
+  $statefile->file('/var/lib/logrotate.status');
+
+  if ( $statefile->check() ) { ...
+
+  $last_rotated_files = $statefile->read();
+
+  ...
+
+  $statefile->write_logfile('/var/log/messages');
+
+=cut
+
+use strict;
+use 5.8.0;
+use warnings;
+
+use Carp qw(:DEFAULT cluck);
+
+#------------------------------------------------------------------------------------
+
+use Data::Dumper;
+use POSIX qw( mktime );
+use Cwd qw(cwd getcwd abs_path);
+
+our $AUTOLOAD;
+our %ok_field;
+
+my $MainVersion = "2.0";
+
+my $Revis = <<'ENDE';
+  $Revision$
+ENDE
+$Revis =~ s/^.*:\s*(\S+)\s*\$.*/$1/s;
+our $VERSION = $MainVersion . "." . $Revis;
+
+$Data::Dumper::Indent = 1;
+$Data::Dumper::Sortkeys = 1;
+
+use constant default_firstline_statusfile => "Logrotate State -- Version 3";
+
+my @ValidFields = qw( parent verbose file test );
+
+for my $attr ( @ValidFields ) {
+  $ok_field{$attr}++;
+}
+
+#------------------------------------------------------------------------------------
+
+=head1 Funktionen
+
+=head2 sub new() - Konstruktor
+
+Wird aufgerufen, um ein neues LogRotate::StateFile-Objekt zu erstellen.
+
+=cut
+
+sub new {
+
+  my $invocant = shift;
+  my $class    = ref($invocant) || $invocant;
+  my ( $res, $cmd );
+
+  my $self = {
+    'verbose'          => 0,
+    'file'     => '/val/lib/logrotate.status',
+    @_
+  };
+
+  $res = bless $self, $class;
+
+  my $p = $self->verbose() ? __PACKAGE__ . "::new(): " : "";
+
+  return $res;
+
+}
+
+#------------------------------------------------------------------------------------------
+
+=head2 AUTOLOAD()
+
+Autoload-Methode zum Zugriff auf alle möglichen Elemente.
+
+=cut
+
+sub AUTOLOAD {
+
+  my $self = shift;
+  my $attr = $AUTOLOAD;
+  my ( $val );
+
+  $attr =~ s/.*:://;
+  $attr = lc($attr);
+
+  croak "Ungueltige Attributmethode ->$attr()" unless $ok_field{$attr};
+
+  return $self->file(@_)    if $attr eq "file";
+  return $self->test(@_)    if $attr eq "test";
+  return $self->verbose(@_) if $attr eq "verbose";
+
+  if ( @_ ) {
+    $val = shift;
+    $self->{uc($attr)} = $val;
+  }
+  return $self->{uc($attr)};
+
+}
+
+#------------------------------------------------------------------------------------------
+
+=head2 check( [$file] )
+
+
+
+=cut
+
+sub check($;$) {
+
+  my $self = shift;
+  my $file = shift;
+  my $p = $self->verbose() ? __PACKAGE__ . "::check(): " : "";
+
+  print $p . "Aufgerufen mit '" . ( defined $file ? $file : "<undef>" ) . "'.\n" if $self->verbose() > 2;
+
+  my $res = $self->read($file);
+
+  return undef unless $res;
+  $file = $self->{'file'};
+
+  unless ( $self->test() ) {
+    if ( open FILE, ">>$file" ) {
+      close FILE;
+    } else {
+      warn $p . "Fehler beim Oeffnen der Status-Datei '$file' zum Schreiben: $!\n";
+      return undef;
+    }
+  }
+
+  return $res;
+
+}
+
+#------------------------------------------------------------------------------------------
+
+=head2 read( [$file] )
+
+Liest die uebergebene Datei in die Konfiguration ein.
+
+Wenn der Parameter $file nicht uebergeben wurde, wird statt dessen $self->{'file'}
+verwendet, welches auch gesetzt wird, wenn $file uebergeben wurde.
+
+Bei Erfolg wird eine Datenstruktur als Hash-Ref uebergeben, deren
+Keys die aus der Datei gelesenen Logdateien sind und deren Values die Zeitstempel
+der rotierten Logdateien.
+
+Bei Misserfolg wird C<undef> zurueckgegeben.
+
+=cut
+
+sub read($;$) {
+
+  my $self = shift;
+  my $file = shift;
+  my $p = $self->verbose() ? __PACKAGE__ . "::read(): " : "";
+
+  my $res = {};
+
+  print $p . "Aufgerufen mit '" . ( defined $file ? $file : "<undef>" ) . "'.\n" if $self->verbose() > 2;
+
+  my ( $f, $dir, $real_dir, $logfile, $date, $time_t );
+
+  $file = $self->{'file'} unless $file;
+  unless ( $file ) {
+    carp $p . "Keine Datei uebergeben.\n";
+    return undef;
+  }
+
+  if ( $file =~ m#/# ) {
+    ( $dir, $f ) = $file =~ m#(.*)/([^/]+)$#;
+  } else {
+    $dir = ".";
+    $f = $file;
+  }
+  $real_dir = abs_path( $dir );
+  print $p . "Real-Path: '$real_dir', Basename: '$f'\n" if $self->{'verbose'} > 2;
+  $f = $real_dir . "/" . $f;
+
+  
+  unless ( -f $file ) {
+    warn $p . "Datei '$file' existiert nicht oder ist keine normale Datei.\n";
+    $self->{'file'} = $f;
+    return $res;
+  }
+
+  print $p . "Lese Datei '$f' ...\n" if $self->verbose();
+  unless ( open FILE, "<$f" ) {
+    warn $p . "Konnte Datei '$f' nicht oeffnen: $!\n";
+    return undef;
+  }
+
+  my $i = 0;
+  while ( <FILE> ) {
+
+    $i++;
+    s/^\s+//;
+    s/\s+$//;
+
+    if ( $i == 1 ) {
+      if ( /^logrotate\s+state\s+-+\s+version\s+[123]$/i ) {
+        next;
+      } else {
+        warn $p . "Inkompatible Version der Statusdatei '$f'.\n";
+        close FILE;
+        return undef;
+      }
+    }
+
+    next unless $_;
+
+    ( $logfile, $date ) = $self->parts( $_ );
+    if ( $logfile and $date ) {
+      my @Date = $date =~ /^\s*(\d+)[_\-](\d+)[_\-](\d+)(?:[\s\-_]+(\d+)[_\-:](\d+)[_\-:](\d+))?/;
+      unless ( @Date ) {
+        warn $p . "Konnte Datum nicht erkennen: '$date' (Datei '$f', Zeile $.).\n";
+        close FILE;
+        return undef;
+      }
+      $time_t = mktime( $Date[5] || 0, $Date[4] || 0, $Date[3] || 0, $Date[2], $Date[1] - 1, $Date[0] - 1900 );
+      unless ( $time_t ) {
+        warn $p . "Unbekanntes Datumsformat: '$date' (Datei '$f', Zeile $.).\n";
+        close FILE;
+        return undef;
+      }
+    }
+
+    $res->{$logfile} = $time_t;
+
+  }
+
+  close FILE;
+  $self->{'file'} = $f;
+  return $res;
+
+}
+
+#------------------------------------------------------------------------------------------
+
+=head2 file()
+
+Setzt bzw. gibt die Status-Datei dieses Moduls zurueck.
+
+=cut
+
+sub file($;$) {
+
+  my $self = shift;
+  my $nv;
+  if ( @_ ) {
+    $nv = shift;
+    $self->{'file'} = $nv if defined $nv;
+  }
+  return $self->{'file'};
+
+}
+
+#------------------------------------------------------------------------------------
+
+=head2 parts( $string )
+
+Zerlegt einen String an Whitespaces in seine Bestandteile unter Beachtung
+von Quotierung und gibt diese als Array zurueck.
+
+=cut
+
+sub parts($$) {
+
+  my $self = shift;
+  my $p = $self->verbose() ? __PACKAGE__ . "::parts(): " : "";
+
+  my $term  = shift;
+  my @Parts = ();
+  my $part;
+
+  while ( $term =~ /"([^"\\]*(?:\\.[^"\\]*)*)"|(\S+)/g ) {
+    $part = $1 || $2;
+    $part =~ s/\\"/"/g;
+    push @Parts, $part;
+  }
+
+  return @Parts;
+
+}
+
+#------------------------------------------------------------------------------------------
+
+=head2 test()
+
+Setzt bzw. gibt den Test-Modus dieses Moduls zurueck.
+
+=cut
+
+sub test($;$) {
+
+  my $self = shift;
+  my $nv;
+  if ( @_ ) {
+    $nv = shift;
+    $self->{'test'} = $nv;
+  }
+  return $self->{'test'};
+
+}
+
+#------------------------------------------------------------------------------------------
+
+=head2 verbose()
+
+Setzt bzw. gibt den Verbose-Level dieses Moduls zurueck.
+
+=cut
+
+sub verbose($;$) {
+
+  my $self = shift;
+  my $nv;
+  if ( @_ ) {
+    $nv = shift;
+    $nv = defined $nv ? ( $nv =~ /(\d+)/ ? $1 : 0 ) : 0;
+    $self->{'verbose'} = $nv;
+  }
+  return $self->{'verbose'};
+
+}
+
+#------------------------------------------------------------------------------------------
+
+1;
+
+__END__
+
+#------------------------------------------------------------------------------------------
+
+=head1 AUTHOR
+
+Frank Brehm <frank@brehm-online.com>
+
+=cut
+
+