Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Help e-mailing last 50 lines of log file

by Anonymous Monk
on Jul 18, 2002 at 15:44 UTC ( #182865=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi All,

I'm running into a little problem. I'm trying to create a script with Perl to tail a log file and send the result vial email.

Thank you in advance,

Clarke

Ultimate Goal...
1. Tail the last 50 lines from a log file on remote machine \\Server\MYlog$\testlog.log
2. Take the tailed data and create a new log file with the date as the file name.
3. Send the log via email.
4. Restart the remote service...(i.e. weblogic)

--- I'm using TAIL.exe for windows. The server is Win2K
with active Perl 5.6 loaded.
--- I'm using MIME::Lite module to send email
--- I'm using Win32::Lanman module

MY Code to Restart Remote service....But I need to first tail the last 50 lines from the log file, create a new log based on that, and send it before I can restart the "weblogic service" on the remote machine. -----------------------------------------------------------

#Example: perl NetRestartService.pl -server SERVER1 service Weblogic - +action RESTART use Getopt::Long; use MIME::Lite; use Win32::Lanman; GetOptions ('server:s', \$server, 'service:s', \$service, 'action:s', +\$action); if ((@ARGV[0] eq "help") || (@ARGV[0] eq "?")){&syntax; exit 1;} if ($server eq ""){$server = $ENV{COMPUTERNAME};} if ($action ne ""){$action = "\U$action\E";} %commands = ('STOP' => 1,'START' => 1,'RESTART' => 1,'AUTOMATIC' => 1, +'MANUAL' => 1,'DISABLED' => 1); if (($action ne "")&&($commands{$action} != 1)) { print "\n\nInvalid command - $action\n\n"; &syntax; exit 1; } %status = ( 1 => 'Stopped', 2 => 'Start Pending', 3 => 'Stop Pending', 4 => 'Running', 5 => 'Continue Pending', 6 => 'Pause Pending', 7 => 'Paused'); %start = (2 => 'Automatically', 3 => 'Manually', 4 => 'Disabled'); %startup = (AUTOMATIC => '2', MANUAL => '3', DISABLED => '4'); if(!Win32::Lanman::EnumServicesStatus("\\\\$server", "", &SERVICE_WIN3 +2, &SERVICE_STATE_ALL, \@services)) { print "\n\nCannot read services information on $server\n\n"; &syntax; exit 1; } foreach (@services) { $state{${$_}{'name'}} = ${$_}{'state'}; if ("\U${$_}{'name'}\E" eq "\U$service\E") { $service = ${$_}{'name'}; $sn = 1; last; } elsif (${$_}{'display'} =~ /$service/i) { @mightbe = (@mightbe, "${$_}{'name'}"); } } if (($sn != 1)&&(@mightbe < 1)) { foreach (@services){print "${$_}{'name'} = ${$_}{'display'}\ +n";} print "\nUnable to locate $service service\n"; exit 1; } if (($sn == 1)&&($action eq "")) { if(!Win32::Lanman::QueryServiceConfig("\\\\$server", '', "$ser +vice", \%config)) { print "Can't query config of $service on $server " . W +in32::Lanman::GetLastError() . "\n"; } print "$service ($config{'display'}) is $status{($state{$servi +ce})} and set to start ${start{$config{'start'}}}\n"; exit 1; } if (($sn == 1)&&($commands{$action} == 1)) { &$action; exit 1; } if ((@mightbe == 1)&&($action eq "")) { $service = $mightbe[0]; if(!Win32::Lanman::QueryServiceConfig("\\\\$server", '', "$ser +vice", \%config)) { print "Can't query config of $service on $server " . W +in32::Lanman::GetLastError() . "\n"; } print "$service ($config{'display'}) is $status{($state{$servi +ce})} and set to start ${start{$config{'start'}}}\n"; exit 1; } if ((@mightbe == 1)&&($commands{$action} == 1)) { $service = $mightbe[0]; if(!Win32::Lanman::QueryServiceConfig("\\\\$server", '', "$ser +vice", \%config)) { print "Can't query config of $service on $server " . W +in32::Lanman::GetLastError() . "\n"; } print "$service ($config{'display'}) is $status{($state{$servi +ce})} and set to start ${start{$config{'start'}}}\n"; if ("\U${start{$config{'start'}}}\E" eq $action) { print "Startup is already ${start{$config{'start'}}} - + No change needed\n"; exit 1; } &$action; exit 1; } if (@mightbe > 1) { print "\n\n\n"; $mbcount = 1; foreach (@mightbe) { print "$mbcount - $mightbe[$mbcount-1] -"; foreach (@services) { if (${$_}{'name'} eq $mightbe[$mbcount-1]) { print " ${$_}{'display'} ($status{$sta +te{${$_}{'name'}}})\n"; } } $mbcount++; } until (($trash > 0)&&($trash <= @mightbe)) { print "\n\nPlease select the service (Ctrl/C to abort) +\n\n"; $trash = <STDIN>; chomp $trash; } $trash = $trash -1; $service = $mightbe[$trash]; if(!Win32::Lanman::QueryServiceConfig("\\\\$server", '', "$ser +vice", \%config)) { print "Can't query config of $service on $server " . W +in32::Lanman::GetLastError() . "\n"; } if ($action eq "") { print "$service ($config{'display'}) is $status{($stat +e{$service})} and set to start ${start{$config{'start'}}}\n"; exit 1; } else { if ("\U${start{$config{'start'}}}\E" eq $action) { print "Startup is already ${start{$config{'sta +rt'}}} - No change needed\n"; exit 1; } &$action; exit 1; } } sub syntax { print "\n\nSYNTAX:\n\nperl sc.pl -server [servername] -servic +e [servicename] -action [action]"; print "\n\n\nEXAMPLES:\n\nperl sc.pl -server server1 -service + spooler -action restart"; print "\n\n\tStops the starts the Spooler service on Server1"; print "\n\nperl sc.pl -server server1 -service spooler "; print "\n\n\tDisplays the current status of the Spooler servic +e on Server1"; print "\n\n\tPossible actions - stop, start, restart, automati +c, manual, disabled\n\n"; } sub STOP { if ($state{$service} != 4) { if ($action eq "RESTART"){return();} print "\n\n$service currently state is $status{($state +{$service})} - Cannot stop\n\n"; exit 0; } if(!Win32::Lanman::StopService("\\\\$server", '', "$service", +\%H1)) { &cstate; print "\n\nError stopping $service service on $server\ +n\nCurrent state is $status{$state}\n"; exit 0; } sleep(2); &cstate; $count = 0; until (($state == 1)||($count == 20)) { sleep(1); &cstate; $count++; } if (($state != 1)&&($count == 20)) { print "\n\nError stopping $service service on $server\ +n\nCurrent state is $status{$state}\n"; exit 1; } print "$service service on $server is $status{$state}\n"; } sub START { if(!Win32::Lanman::StartService("\\\\$server", '', "$service") +) { print "\n\nError starting $service service on $server\ +n\n"; exit 0; } sleep(2); &cstate; $count = 0; until (($state == 4)||($count == 20)) { sleep(1); &cstate; $count++; } if (($state != 4)&&($count == 20)) { print "\n\nError starting $service service on $server\ +n\nCurrent state is $status{$state}\n"; exit 1; } print "$service service on $server is $status{$state}\n"; } # SENDING EMAIL --------------------------- sub send_email () { my $msg; MIME::Lite->send('smtp', "192.168.2.3", Timeout=>60); $msg = MIME::Lite->new( From =>'NetRestartService', To =>'Test@test.com', Cc =>'Test2@test2.com', Subject =>'Perl Script to restart reomote NT Service - + NetRestartService.pl', Data =>'This email was generated after an error was + detected, the NetRestartService.pl script was executed.', ); $msg->send; } # END SENDING EMAIL --------------------------- sub RESTART { &STOP; &START; } sub AUTOMATIC { &CHANGE; } sub MANUAL { &CHANGE; } sub DISABLED { &CHANGE; } sub CHANGE { print "Modifying startup parameter of $service on $server\n"; if (!Win32::Lanman::ChangeServiceConfig("$server", "" ,"$servi +ce", {start => "$startup{$action}"})) { print "Unable to update the $service service configura +tion on $server\n"; return; } if(!Win32::Lanman::QueryServiceConfig("\\\\$server", '', "$ser +vice", \%config)) { print "Can't query config of $service on $server " . W +in32::Lanman::GetLastError() . "\n"; } print "$service is $status{($state{$service})} and set to star +t ${start{$config{'start'}}}\n"; exit 1; } sub cstate { if(!Win32::Lanman::EnumServicesStatus("\\\\$server", "", &SERV +ICE_WIN32, &SERVICE_STATE_ALL, \@services)) { print "\n\nCannot read services information on $server +\n\n"; exit 0; } foreach (@services) { if (${$_}{'name'} eq $service) { $state = ${$_}{'state'}; } } }

Edit by tye

Replies are listed 'Best First'.
Re: Help e-mailing last 50 lines of log file
by Abigail-II (Bishop) on Jul 18, 2002 at 15:58 UTC
    Urgle. All that to send 50 lines by email? I am so glad I work on Unix. There it takes just one line, and you don't even need Perl:
    $ tail -50 $log_file | mailx -s "50 lines." me@example.org

    Abigail

      Ha, ha, ha ... you are soooo funny.

      But the AnonymousMonk seems to be a little confused as well. The lengthy code does a lot of things, but there's no tailing and mailing. What is the real question? How to get the results of tail.exe? Or how to include them in the email? Or what? And why did you include the service related code?

      I think you want something like this:

      $loglines = `tail -50 $logfile`; $message = <<"*END*"; This email was generated after an error was detected, the NetRestartService.pl script was executed. Log file: $loglines *END* $msg = MIME::Lite->new( From =>'NetRestartService', To =>'Test@test.com', Cc =>'Test2@test2.com', Subject =>'Perl Script to restart remote NT Service - NetRestartServ +ice.pl', Data => message , ); $msg->send;

        Jenda

        Hi Jenda,

        Sorry for the confusion with the code above...I didn't put everything on the forum correctly. It was missing lots of code. I'm faily new at PERL and I'm learning as I go, putting bits and pieces of code together that I've obtained on the internet.

        I don't know how to put everything together. This is the first code section I want to use....The code will use "TAIL.exe" placed in the WINNT\SYSTEM32 directory. How do I get the the "TAILED" result from the "LOG1.LOG" and create a new log with that informaton. Once this is done, I need to send an email with the newly created log file. Once the email is sent the weblogic service needs to be restarted. (I want to run the scipt remotely).

        - Can I specify remote machines to run this script, for example "\\Server1\Logs\testlog.log" and remote service to restart "weblogic".

        *** THANKS AGAIN JENDA FOR YOUR WISDOM! ******
        PLEASE HELP ME PUT THIS TOGETHER.....

      Q: How do I do X on Windows?
      A: First install UNIX . . . :)

      Of course one can install Cygwin and get perfectly good versions of tail et al.

Re: HELP!!!!!!
by chromatic (Archbishop) on Jul 18, 2002 at 16:07 UTC

    Start with a good text editor. Type in your code. Save it. Run it. If there are warnings or errors fix them. When it works as per your specification you are done. Very easy!

    Oh, and be careful that $\ isn't interpreted as a magic variable. You'll probably want to use single quotes to avoid interpolation when you're opening the file. Maybe Tie::File would be more useful?

Re: Help e-mailing last 50 lines of log file
by samgold (Scribe) on Jul 19, 2002 at 00:22 UTC
    This will read a file backwards untill yestersdays date. If your log file is large try file::Readbackwards.
    my $file; my @lines; open FH, 'yourlogfile.log'; @lines = <FH>; LINE: while ($file = pop @lines) { if ( $file =~ m/^ERR*/ ) { print "$file\n"; } last LINE if ($file !~ m/^$today*/ && $file =~ m/^(\S+\s+\S+\s+\d+)\s+\d+:\d+:\d+\s+(\d+)/x ); }
    Or you can try this...
    Recommended by runrig
    If the log file is large (which log files sometimes tend to be) then you might want to use File::ReadBackwards or risk getting an 'Out of memory' error.

    I hope that helps.
    Sam

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://182865]
Approved by Russ
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (3)
As of 2022-10-07 09:29 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My preferred way to holiday/vacation is:











    Results (29 votes). Check out past polls.

    Notices?