perl-win32-users-boun...@listserv.activestate.com wrote on 06/05/2012 
03:00:02 PM:
> A non-text attachment was scrubbed...
> Name: pullFromEventLog.pl

It was a text attachment, you silly little program...  Well, I don't know 
how to get my mailer to send text only, so I can't blame it much.

Its only 250 lines, so hopefully the list will not mind if I post it 
directly.

#!c:\perl\bin\perl.exe
# vim:sw=2:et:ic:sm:syn=perl:nu
#
# $Id: pullFromEventLog.pl,v 1.4 2009/12/28 14:24:57 edf78qd Exp edf78qd $
#
# $Log: pullFromEventLog.pl,v $
# Revision 1.4  2009/12/28 14:24:57  edf78qd
# Cleaned up the CIM into a standard mysql datetime format before 
insertion.
#
# Revision 1.3  2009/09/24 22:05:48  edf78qd
# Added some docs
#
# Revision 1.2  2009/09/21 13:36:09  edf78qd
# made it a stand-alone, so that it would run as a child process.
# Added some instrumentation to log.$$.log
#
# Revision 1.1  2009/09/18 19:04:42  edf78qd
# Initial revision
#

=pod

Database structure for table logentries: most of these come straight from
windows event log fields (as seen below).  I just add "host" and "string"
at the end (for the FQDN host containing log entry, and the string that 
the
host is in).

+------------------+------------------+------+-----+---------+----------------+
| Field            | Type             | Null | Key | Default | Extra    |
+------------------+------------------+------+-----+---------+----------------+
| logID            | int(10) unsigned | NO   | PRI | NULL    | 
auto_increment |
| Category         | int(10) unsigned | YES  |     | NULL    |    |
| CategoryString   | tinytext         | YES  |     | NULL    |    |
| ComputerName     | tinytext         | YES  |     | NULL    |    |
| Data             | text             | YES  |     | NULL    |    |
| EventCode        | int(10) unsigned | YES  |     | NULL    |    |
| EventIdentifier  | int(10) unsigned | YES  |     | NULL    |    |
| EventType        | int(11)          | YES  |     | NULL    |    |
| InsertionStrings | text             | YES  |     | NULL    |    |
| LogFile          | tinytext         | YES  |     | NULL    |    |
| Message          | text             | YES  |     | NULL    |    |
| RecordNumber     | int(10) unsigned | YES  |     | NULL    |    |
| SourceName       | tinytext         | YES  |     | NULL    |    |
| TimeGenerated    | datetime         | YES  |     | NULL    |    |
| TimeWritten      | datetime         | YES  |     | NULL    |    |
| Type             | tinytext         | YES  |     | NULL    |    |
| User             | tinytext         | YES  |     | NULL    |    |
| Host             | tinytext         | YES  |     | NULL    |    |
| string           | tinytext         | YES  |     | NULL    |    |
+------------------+------------------+------+-----+---------+----------------+

=cut
use strict;
use Win32::OLE qw(in);
use Getopt::Std;
use DBI;
my $now   = time;
my $DEBUG = 0;
$| = 1;
our %opts;
getopts( 'hu:p:s:H:', \%opts );

if ( $opts{'h'} ) {
  print <<EOH;
usage: $0 [-h] -u username -p password
  -h this message
  -u domain qualified username (e.g. ad\\hashid)
  -p password, in quotes if necessary
  -s string (for addition to DB)
  -H limit to specific hosts (comma delimited)
EOH
  exit;
}
my $TEXT = "
class Win32_NTLogEvent
{
  uint16   Category;
  string   CategoryString;
  string   ComputerName;
  uint8    Data[];
  uint16   EventCode;
  uint32   EventIdentifier;
  uint8    EventType;
  string   InsertionStrings[];
  string   Logfile;
  string   Message;
  uint32   RecordNumber;
  string   SourceName;
  datetime TimeGenerated;
  datetime TimeWritten;
  string   Type;
  string   User;
};
";
my ( $mib, @properties ) = text2properties($TEXT);
my $FQDN = $opts{'H'};
if ($DEBUG) {
  open F, '>', "log.$$.log" or die "can't open log.$$.log: $_";
}
print "Process $$ to $FQDN (" . localtime(time) . ")\n";
print F "Process $$ to $FQDN (" . localtime(time) . ")\n" if $DEBUG;
my $locatorObj = Win32::OLE->new('WbemScripting.SWbemLocator')
  || die "Error creating locator object: "
  . Win32::OLE->LastError() . "\n";
$locatorObj->{Security_}->{impersonationlevel} = 3;
#  $locatorObj->{Security_}->{setdebugpriviledge} = 1;
my $rv        = 0;
my $serverObj = $locatorObj->ConnectServer(    # connect to WMI server
  $FQDN,                                       # on this host
  'root\cimv2',                                # this namespace
  $opts{'u'},                                  # user
  $opts{'p'}
  )                                            # password
  || ( $rv = 1 );
if ($rv) {
  print "Process $$ had an error connecting to $FQDN: "
    . Win32::OLE->LastError() . "\n";
  print F "Process $$ had an error connecting to $FQDN: "
    . Win32::OLE->LastError() . "\n"
    if $DEBUG;
  exit;
}
my $dbh = DBI->connect( 'DBI:mysql:eventlogs', 'woody', '' )
  or die "Can't connect to mysql: $!";
my $sth = $dbh->prepare(
  "SELECT lastEntry FROM newestlogs WHERE Host LIKE '$FQDN'")
  or die "Can't prepare search for max: " . $dbh->errstr();
$sth->execute()
  or die "Can't execute search for max: " . $dbh->errstr();
my $ref        = $sth->fetchrow_arrayref;
my $searchTime = convert2CIM( $$ref[0] );
my $preparestr =
"INSERT INTO logentries VALUES (0, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 
?, ?, ?, '$FQDN', '$opts{'s'}')";
$sth = $dbh->prepare($preparestr)
  or die "Can't prepare insert: " . $dbh->errstr();
my $once  = 0;
my $count = 0;
print "looking for log entries since $searchTime\n";
print F "looking for log entries since $searchTime\n" if $DEBUG;
my $newestLogDate;

foreach my $obj (
  in $serverObj->ExecQuery(
"SELECT * FROM WIN32_NTLogEvent WHERE (TimeGenerated > '$searchTime')",
    'WQL',
    48
  )
  ) {
  $count++;
  if ( not $once ) {
    print "DB call for $FQDN returned in "
      . ( time - $now )
      . " seconds\n";
    print F "DB call for $FQDN returned in "
      . ( time - $now )
      . " seconds\n"
      if $DEBUG;
    $once = 1;
  }
  my @params = ();
  foreach my $property (@properties) {
    if ( ref $obj->{$property} eq 'ARRAY' ) {
      my $str = join( ",", @{$obj->{$property}} );
      $str =~ tr/\r\n\t/   /s;
      push @params, $str;
    } elsif ( $property eq 'Message' ) {
      my $mess = $obj->{$property};
      $mess =~ tr/\r\n\t/   /s;
      push @params, $mess;
    } elsif ( ( $property eq 'TimeGenerated' )
      or ( $property eq 'TimeWritten' ) ) {
      my $time = $obj->{$property};
      push @params, convertFromCIM($time);
    } else {
      push @params, $obj->{$property};
    }
  } ## end foreach my $property (@properties)
  $sth->execute(@params)
    or die "$$ can't insert params ", join( ", ", @params ),
    " sorry. " . $dbh->errstr();
  $newestLogDate = $obj->{TimeGenerated};
} ## end foreach my $obj ( in $serverObj...
print "Captured $count NT Event Log records for $FQDN\n";
print F "Captured $count NT Event Log records for $FQDN\n" if $DEBUG;
updateNewestLogs( $FQDN, $newestLogDate );
exit;    # main

sub text2properties {
  my @tokens = split( /\s+/, shift );
  my $i = 0;
  while ( ( $i < $#tokens ) and ( $tokens[$i] ne 'class' ) ) {
    $i++;
  }
  if ( $tokens[$i] ne 'class' ) {
    die "Please check your input text, couldn't find 'class'\n";
  } else {
    $i++;
  }
  my $mib = $tokens[$i];
  my @rv;
  foreach my $token (@tokens) {
    if ( $token =~ /;/ ) {
      chop $token;
      next if ( $token eq '}' );
      if ( $token =~ /\[/ ) {
        chop $token;
        chop $token;
      }
      push @rv, $token;
    }
  }
  return ( $mib, @rv );
} ## end sub text2properties

sub convert2CIM {
  my $time = shift;
  return '20090917000000.000000-240'
    if not defined $time;    # day zero of the run
   # probably something related to real time would be better, maybe 'start 
from yesterday'
  if ( $time =~ m/(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)/ ) {
    return sprintf( '%04d%02d%02d%02d%02d%02d.000000-300',
      $1, $2, $3, $4, $5, $6 );
  } else {
    die "bad time $time\n";
  }
}

sub convertFromCIM {
  my $CIM = shift;
  if ( $CIM =~ /^(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)\.\d+-300$/ ) {
    return
      sprintf( '%04d-%02d-%02d %02d:%02d:%02d', $1, $2, $3, $4, $5,
      $6 );
  } else {
    die "Bad CIM $CIM\n";
  }
}

sub updateNewestLogs {
  my $host = shift;
  my $date = convertFromCIM(shift);
  my $sth =
    $dbh->prepare("UPDATE newestlogs SET lastEntry=? WHERE host=?")
    or die "can't prepare update for newestlogs: " . $dbh->errstr();
  $sth->execute( $date, $host )
    or die "can't update newestlog setting $host to $date: "
    . $dbh->errstr();
}
_______________________________________________
Perl-Win32-Users mailing list
Perl-Win32-Users@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

Reply via email to