Oracle FAQ Your Portal to the Oracle Knowledge Grid
HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US
 

Home -> Community -> Usenet -> c.d.o.misc -> Re: Freebie: read/grep alert log from sqlplus

Re: Freebie: read/grep alert log from sqlplus

From: Ivan Saez <i.a.saez.scheihing_at_tue.nl>
Date: Tue, 28 May 2002 07:47:28 +0200
Message-ID: <3CF319F0.B40E57AD@tue.nl>


I wrote something similar but in Perl. It runs as a crontab-job and scans all alert-log files on a machine every hour and mails any error found. I wrote this tool when we had problem with the intelligent agent and had to check alert-logs on different machines with different OS (unix, openvms). The scanning of the alert-logs is sequential but it is still fast (on hour machines
at least). The script expects the alert-log files in OFA complaint directory: /u01/app/oracle/admin/<INSTANCENAME>/bdump/alert_<INSTANCENAME>.log To scheduled the script I use :

0 0-23 * * * (cd Alert; ./alert_log.pl) > /dev/null

#! By I. Saez: Looks for ora- errors in alert-log #! Oracle instances. Range is between current date and hour and previous hour (and date)
#! date format Oracle in alert-log : Thu Aug 2 16:34:27 MET DST 2001 #!

$mailprog = "/usr/lib/sendmail -t -oi"; # email-program
$mailto = "i.a.saez.scheihing\@tue.nl"; # change to your email
$subject = "Errors found in";
$from = "i.a.saez.scheihing\@tue.nl";
$cc = "";
$date = `date`;
$adebug = 0; # set to 1 for debug info

chop($date);

$date = substr($date,0,index($date,":")-2); # example: Tue May 28
$hour = `date +'%H'`; # example: 07
chop($hour);

$now = $date.$hour; # Tue May 28 07

# hour = 0
if ($hour == 0 ) {

        # 12 o'clock in the evening; go one day back
        $hour   = 23;
        # previous day

        ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
localtime(time-86400);
        $y+=1900;
        $mon  = (Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec)[$mon];
        $dag = (Sun,Mon,Tue,Wed,Thu,Fri,Sat)[$wday];
        $date =  ( $mday < 10 ) ? $dag.' '.$mon.'  '.$mday : $dag.' '.$mon.'
'.$mday;

}
else {

        $hour = $hour - 1
}

# previous hour
if ( $hour < 10 ) {

   $prev = $date.'0'.$hour;
} else {

   $prev = $date.$hour;
}

$nodenaam = `hostname`;

#
open ORA,"/var/opt/oracle/oratab" || die "Can't open /var/opt/oracle/oratab";

while (<ORA>) {

# read all instance names
 chop;
# print $_;
 if ( /#/ || /^$/ ) {

    # skip comment and empty lines
 } else {
  # get instance name
  ( $inst,$home,$start) = split(/:/);
  # Alert log-file name plus path; works only if OFA is used!!!   $alert_log = "/u01/app/oracle/admin/$inst/bdump/alert_$inst.log"; #
if ($adebug) {
print qq|

Alert log : $alert_log
Hour      : $hour
now       : $now
Prev      : $prev

|;
}

 &CHECK_LOG( $alert_log,$inst);
#
} # if (index($_,"#") ) {
} # while (<ORA>) {
close ORA;

exit;

sub CHECK_LOG ()
{
  # scan alert_log between now ($now) and one hour back ($prev)   print qq|
   Scanning alert file $alert_log of instance $inst    between "$prev" en "$now"
  |;

  $i = 0;
  $mailbool = 0;
  $bool = 0;

  %mailarr = ();
  $j = 0;
  open(IN, $alert_log) || die 'Cannot open alert log $alert_log';   while (<IN> ) {

   chop;
   if ( /$prev/ || $bool ) {

     # here scan for ora- errors
     if ( /ORA-/ || /Errors in/ ) {

       $mailbool = 1;
       $mailarr{$j++} = $_;

     } # if ( /ORA-/ ) {
     $bool = 1;       # keep scanning

    } #if ( /$prev/ || $bool ) {
    if ( /$now/ ) {

      $bool = 0;      # no more scanning
      $last;

    } # if ( /$now/ ) {

   $i++;
  } # while (<IN> ) {

  &Mail_errors() if $mailbool;

print qq|
 $i lines scanned
|;

close (IN);

}

sub Mail_errors () {

print "in Mail_errors\n";
open ( MAIL,"|${mailprog} " ) || die "can't open $mailprog!";;

print MAIL "To: ${mailto}\r\n";
print MAIL "Cc: ${cc}\r\n";
print MAIL "From: ${from}\r\n";
print MAIL "Subject: $subject $alert_log!\r\n";
print MAIL "\r\n";
print MAIL "Between $prev and $now \r\n";
foreach $key ( sort keys %mailarr ) {
  print MAIL "${mailarr{$key}}\r\n";
}
close ( MAIL );

} # end sub Mail_errors

Steve Perry wrote:

> I thought this might be useful to somebody. I wrote it (with help from
> metalink and akadia) because I hated having to telnet to different servers
> to look at the alert log.  save it off in directory, start sqlplus and type
> @alertlog. It will show you filtered errors in it. If you don't manage the
> alertlogs and archive them weekly or monthly, this can take a bit to run. On
> my systems, it takes a few seconds. I'm almost done converting it to a
> package with more features (i.e. date range, you don't have keep creating
> the directory).  It does require v8.0+ and the utl_raw package. Other than
> that, it should work just fine.
>
> If you see areas for improvement, let me know.
>
> Steve
>
> rem clear screen
> set echo off
> set lines 150
> set arraysize 120
>
> --
> * ------------------------------------------------------------------------ *
> -- * @alertlog
> *
> -- * FILE:   alertlog.sql
> *
> -- * SOURCE: "glued" together code from metalink, akadia and my own
> *
> -- * AUTHOR: Steve Perry and above mentioned caveats.
> *
> -- * EMAIL : sperry_at_sprynet.com
> *
> -- * DATE  : 3/15/02
> *
> -- * INPUT : none
> *
> -- * OUTPUT: report
> *
> -- * ORACLE: 8.0.x and above.
> *
> -- * Restrictions: assumes the path is "hardcoded" and no env vars.
> *
> -- * DESCRIPTION: displays info about errors and things of interest in the
> *
> -- *              database alert log.
> *
> -- *
> *
> -- * Maintenance
> *
> -- * SMP 3/15/02  Created,                                      *
> -- * smp        3/18/02         modified for Unix support and alertlog
> default*
> -- *     names: Unix   : alert_<sid>.log               *
> -- *            Windows: <sid>ALRT.LOG                 *
> -- *
> *
> --
> * ------------------------------------------------------------------------ *
>
> set verify off
> set feedback off
>
> --Determine the OS (WIN or UNIX)
> col OS_PLATFORM new_value OS_PLATFORM noprint
> select decode(instr(upper(product), 'WINDOWS',1), 0 , 'UNIX', 'WINDOWS')
> OS_PLATFORM
>   from PRODUCT_COMPONENT_VERSION
>  WHERE upper(PRODUCT) LIKE 'TNS%'
> /
>
> col dirname new_value dirname noprint
> select decode('&OS_PLATFORM', 'WINDOWS', value || '\', value || '/') dirname
>   from v$parameter
> where name = 'background_dump_dest'
> /
>
> -- debug stuff
> -- prompt dir = &&dirname
>
> create or replace directory "ALERTDIR" as '&&dirname';
>
> --allows leading whitespace to be printed by dbms_output
> SET SERVEROUTPUT ON FORMAT WRAPPED
>
> rem clear screen
>
> -- ****************************************************************
> -- BEGIN CODE PART
> -- ****************************************************************
>
> DECLARE
> -- Input Directory as specified in create directory
> l_dir       CONSTANT VARCHAR2(30) := 'ALERTDIR';
>
> -- Input File which is read word by word
> l_fil       VARCHAR2(30) ;
> l_fil_size  number;
>
> -- Separator Character between words is a BLANK (ascii = 32)
> l_sep       CONSTANT RAW(500) := UTL_RAW.CAST_TO_RAW(CHR(32));
> l_eol       CONSTANT RAW(500) := UTL_RAW.CAST_TO_RAW(CHR(10));
>
> -- Character at the end of the file is NEWLINE (ascii = 10)
> l_sen       CONSTANT RAW(500) := UTL_RAW.CAST_TO_RAW(CHR(10));
>
> -- Pointer to the BFILE
> l_loc       BFILE;
> --l_mode_RO   BINARY_INTEGER := file_readonly;
>
> -- Current position in the file (file begins at position 1)
> l_pos       NUMBER := 1;
>
> -- Amount of characters have been read
> l_read_amt       BINARY_INTEGER := 0;
>
> -- Read BufferS
> l_rawbuf    raw(500);
> l_buf       VARCHAR2(500);
>
> -- End of the current line which will be read
> l_end       NUMBER;
>
> -- Return value
> l_ret       BOOLEAN := FALSE;
>
> -- DB Name to resolve alert log
> l_ora_sid varchar2(30);
>
> -- work date var
> l_date       date;
>
> --alert string
> l_alrt   varchar2(10);
>
> --debug setting
> bDebug  boolean := FALSE;
>
> --OS PLATFORM
> l_OS_PLATFORM  varchar2(15) := 'WINDOWS';
>
> BEGIN
>     -- set the max buffer size
>     dbms_output.enable(1000000);
>
>     --get database name
>     select value into l_ora_sid from sys.v_$parameter where name =
> 'db_name';
>
>     --Determine the OS (WIN or UNIX)
>     select decode(instr(upper(product), 'WINDOWS',1), 0 , 'UNIX', 'WINDOWS')
> into l_OS_PLATFORM
>       from sys.PRODUCT_COMPONENT_VERSION
>      WHERE upper(PRODUCT) LIKE 'TNS%';
>
>     --set the alert file name now
>     if l_OS_PLATFORM = 'WINDOWS' then
>            l_fil := l_ora_sid || 'ALRT.LOG';
>     else
>            l_fil := 'alert_' || l_ora_sid || '.log';
>     end if;
>
>     -- Mapping the physical file with the pointer to the BFILE
>     l_loc := BFILENAME(l_dir,l_fil);
>
>     dbms_output.put_line('File: ALERTLOG.SQL - Compliments of SQL*Buddy
> (Steve Perry)...' );
>     dbms_output.put_line('Date: ' || to_char(sysdate, 'DY, MON DD HH24:MI:SS
> YYYY')  );
>     dbms_output.put_line('Processing alert.log for sid: ' || l_ora_sid );
>     dbms_output.put_line('Opening File ' || l_fil || ' in Directory ' ||
> l_dir );
>
>     -- Check if the file exists
>     l_ret := DBMS_LOB.FILEEXISTS(l_loc) = 1;
>     IF (l_ret) THEN
>        -- Open the file in READ_ONLY mode
> --       DBMS_LOB.OPEN(l_loc, DBMS_LOB.LOB_READONLY);
>        DBMS_LOB.FILEOPEN(l_loc, DBMS_LOB.file_readonly );
>
>        l_fil_size := DBMS_LOB.GETLENGTH( l_loc );
>        dbms_output.put_line('Alert log size is: ' ||
> ltrim(to_char(l_fil_size, '999,999,999,999,999')) || ' bytes.' || chr(10));
>
>        --print heading
>        dbms_output.put_line(chr(10) || 'Date
> Description');
>
> bms_output.put_line('-------------------------    --------------------------
> --------------------------------------');
>
>        /**************/
>        LOOP
>        /*************/
>           -- find the end of the current line
>           l_end := DBMS_LOB.INSTR(l_loc,l_eol,l_pos,1);
>           -- Process end-of-file
>           --only goes into here if: reached end of file l_end = 0
>           IF (l_end = 0) THEN
>             l_end := DBMS_LOB.INSTR(l_loc,l_eol,l_pos,1);
>             l_read_amt := l_end - l_pos - 1;
>             --debug stuff
>             IF bDebug then
>                dbms_output.put_line(' --------------- ' );
>                dbms_output.put_line('l_fil_size: ' || to_char(l_fil_size,
> '999,999,999,999') );
>                dbms_output.put_line('l_end:      ' || to_char(l_end ,
> '999,999,999,999'));
>                dbms_output.put_line('l_read_amt: ' || to_char(l_read_amt ,
> '999,999,999,999'));
>                dbms_output.put_line('l_pos:      ' || to_char(l_pos ,
> '999,999,999,999'));
>                dbms_output.put_line('l_rawbuf:   ' ||
> UTL_RAW.CAST_TO_VARCHAR2(l_rawbuf) );
>                dbms_output.put_line(' --------------- ' );
>                --debug stuff
> --             DBMS_LOB.READ(l_loc,l_read_amt,l_pos,l_rawbuf);
> --               l_buf := UTL_RAW.CAST_TO_VARCHAR2(l_rawbuf);
> --               dbms_output.put_line(l_buf);
>                EXIT;
>             END IF;
>           END IF;
>
>           --set chunk of data to read
>           l_read_amt := l_end - l_pos;
>           -- Read until end-of-file
>           DBMS_LOB.READ(l_loc,l_read_amt,l_pos,l_rawbuf);
>
>           --debug stuff
> --          if bDebug then
> --             dbms_output.put_line(' --------------- ' );
> --             dbms_output.put_line('l_end:      ' || to_char(l_end ,
> '999,999,999,999'));
> --             dbms_output.put_line('l_read_amt: ' || to_char(l_read_amt ,
> '999,999,999,999'));
> --             dbms_output.put_line('l_pos:      ' || to_char(l_pos ,
> '999,999,999,999'));
> --             dbms_output.put_line(' --------------- ' );
> --             --debug stuff
> --          end if;
>
>           --convert the line to character data
>           l_buf := UTL_RAW.CAST_TO_VARCHAR2(l_rawbuf);
>           --if win os, strip off the chr(12), otherwise leave it alone.
>           if l_OS_PLATFORM = 'WINDOWS' then
>              l_buf := substr(l_buf, 1, length(l_buf) - 1);
>           end if;
>
>           --hack to find the date (line prior to error)
>           if substr(l_buf, 4,1) = ' ' then
>              begin
>                 -------select to_date('Tue Mar 12 03:24:18 2002', 'DY, MON
> DD HH24:MI:SS YYYY') from dual
>                 select to_date(l_buf, 'DY, MON DD HH24:MI:SS YYYY') into
> l_date from dual;
>              exception
>                 when others then
>                    l_date := null;
>              end;
>           end if;
>           IF instr(l_buf,'ORA-'                     , 1 ) > 0
>              or instr(l_buf,'Starting up ORACLE'    , 1 ) > 0
>              or instr(l_buf,'Shutting down instance', 1 ) > 0
>              or instr(l_buf,'Errors in'             , 1 ) > 0
>              or instr(l_buf,'alter database '       , 1 ) > 0
>              or instr(l_buf,'Completed: alter data' , 1 ) > 0    then
>                 --hilight errors...
>                 if instr(l_buf, 'ORA-', 1) > 0 then
>                    l_buf  := ' !! ' || ltrim(l_buf);
>                    l_alrt := chr(10);
>                 else
>                    l_buf := '    ' || ltrim(l_buf);
>                    l_alrt := '';
>                 end if;
>                 dbms_output.put_line(l_alrt || to_char(l_date, 'DY, MON DD
> HH24:MI:SS YYYY') || l_buf);
> --               dbms_output.put_line(' - ' || l_buf);
>           END IF;
>           --move pointer to next part of data
>           l_pos := l_pos + l_read_amt + 1;
>           IF l_pos > l_fil_size THEN
>              exit;
>           END IF;
>        /***********/
>        END LOOP;
>        /***********/
>        --close the file normally
>        DBMS_LOB.FILECLOSE(l_loc);
>        dbms_output.put_line( chr(10) ||  chr(10) );
>     ELSE
>        dbms_output.put_line(chr(10) || 'File ' || l_fil || ' in Directory '
> || l_dir || ' was NOT FOUND' || chr(10));
>     END IF;
>
> EXCEPTION
>     WHEN OTHERS THEN
>         dbms_output.put_line('Error: ' || SQLERRM);
>         DBMS_LOB.FILECLOSE(l_loc);
> END;
> /
>
> drop directory "ALERTDIR"
> /
>
> set verify off
> set feedback on
> set echo on
Received on Tue May 28 2002 - 00:47:28 CDT

Original text of this message

HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US