1752777 Members
6342 Online
108789 Solutions
New Discussion

Re: Please explain

 
Alok_Behria
Advisor

Please explain

 

Hi All,

 

OS :- HPUX 11.11

 

I have got the following shell script, which I have managed to found , while googled. let me explain you about the script, this script actually search for the alert.log  file,  which contains the critical database errors and mail across the errors, if contains the string matching "ORA-" .The following script does serve the purpose for me, but since I am new to the shell scripting, I was struggling to grab it. I have commebted out , where I require the explannation from you people. Please go throught and explain, that would be really apprciated.

 

#!/bin/bash
ALERT_LOG=/db/$ORACLE_SID/oracle/admin/$ORACLE_SID/bdump/alert_$ORACLE_SID.log
MAXSIZE=1000000   ## please explain
LINES_KEPT=1000   ## please explain
if [ -f $ALERT_LOG.prev ] ; then # just wondering, how can we use this, since we did not declare this.
   PREVSIZE=`ls -l $ALERT_LOG.prev | awk '{print $5}'` # please explain
   dd if=$ALERT_LOG of=/tmp/alert.log bs=$PREVSIZE skip=1 # please explain
   CHECKFILE=/tmp/alert.log
else
   PREVSIZE=0
   CHECKFILE=$ALERT_LOG
fi
if [ "`grep 'ORA-' $CHECKFILE`" ] ; then
       mailx -s  "Alerr log has errors" abc@xyz.com > $CHECKFILE
else
:
fi
if [ $PREVSIZE -gt $MAXSIZE ] ; then # please explain
  tail -$LINES_KEPT $ALERT_LOG > $ALERT_LOG.new # please explain
  mv $ALERT_LOG.new $ALERT_LOG
fi
cp $ALERT_LOG $ALERT_LOG.prev

 

4 REPLIES 4
James R. Ferguson
Acclaimed Contributor

Re: Please explain

Hi:

 

First, never be afraid to consult the manpages for help in understanding what a particular command does (in general or specifically with the options you see deployed).

 

As a beginning guide to shell scripting, I always recommend this :

 

There is a PDF version of the Shell Users Guide there too:

 

http://web.archive.org/web/20081231081339/http://docs.hp.com/en/hpux10.x.html

Whatever you do, avoid the C-shell.

 

If you are a Linux user, the Bash shell is the de facto standard.  It has a great many enhacements over the POSIX or Korn shells.  With HP-UX, the POSIX shell (found in '/usr/bin/sh' or as '/sbin/sh' for the root account) is the standard shell and I suggest that that be your choice when on that platform.  Avoid the C-shell as it is badly broken.

 

Excellent script samples and tutorials can be found here:

 

http://www.shelldorado.com/

As for you specific questions, here are some pointers:

 

> MAXSIZE=1000000 # set the value of the variable MAXSIZE to 1000000

 

> if [ -f $ALERT_LOG.prev ] ; then # this tests for the presence of a file whose name is composed of the

*value* of '$ALERT_LOG' with the string '.prev' added to the end.

 

> PREVSIZE=`ls -l $ALERT_LOG.prev | awk '{print $5}'` # please explain

 

The backticks tell the shell to *run* the 'ls' command and pipe (pass along) its ouput to 'awk' which should then print only the fifth (5th) whitespace-delimited field of each line.  Whatever is printed (if anything) is assigned to the 'PREVSIZE' variable.

 

I will let you look up 'dd' and 'tail' as a learning exercise.

 

It is important to note that the use of the backtick syntax is archaic and better done with:

 

$( ... )

 

Thus:

 

PREVSIZE=`ls -l $ALERT_LOG.prev | awk '{print $5}'`

...becomes;

 

PREVSIZE=$(ls -l $ALERT_LOG.prev | awk '{print $5}')

...which greatly improves readability and avoids typing mistakes where a backtick and a single quote are interchanged.

 

Another good habit to form is to enclose variable dereferencing (interpolation) in curly braces.  By this I mean, instead of writing:

 

if [ -f $ALERT_LOG.prev ] ; then

...do this, instead:

 

if [ -f ${ALERT_LOG}.prev ] ; then 

This helps you quickly see that the variable part is the variable named 'ALERT_LOG'.  It tells the shell that something like:

 

if [ -f ${ALERT_LOG}prev ] ; then

...is really a test for a file named with the suffix "prev" and not a reference to a variable named "ALERT_LOGprev" if the curly braces were omitted.

 

Regards!

 

...JRF...

 

donna hofmeister
Trusted Contributor

Re: Please explain

1st -- what james said!  (this script really could use some work...) (and man pages are your friend!)

 

2nd -- break the script into pieces and run the lines that you have questions about -- from your session -- to see what happens.

 

this line -- if [ -f $ALERT_LOG.prev ] -- is asking if this file exists.  it also takes the value of ALERT_LOG (see line 2) and adds ".prev" to it.  do an 'll' to see what's in the directory to know for yourself if this if statement will be true or false. 

 

do the "ls -l" to see if you can determine what field $5 is.  then redo the "ls -l" and pipe it to awk (just like in the script) to see what's actually returned and recorded as PREVSIZE. 

 

now that PREVSIZE has a value, can you figure out what the dd does?  Can you plug-in the values of PREVSIZE and MAXSIZE to understand how the 'if...-gt' statement works?

 

 

Dennis Handly
Acclaimed Contributor

Re: Please explain script

>if [ "`grep 'ORA-' $CHECKFILE`" ] ; then

 

You may want to change this to the more obvious:

grep -q 'ORA-' $CHECKFILE

if [ $?-eq 0 ] ; then

 

Or:

if grep -q 'ORA-' $CHECKFILE; then

 

Laurent Menase
Honored Contributor

Re: Please explain

First of all, if the file is modified while in that script, you can miss events.

For instance if a new event happens between dd and the final cp.

also when

  tail -$LINES_KEPT $ALERT_LOG > $ALERT_LOG.new # please explain
  mv $ALERT_LOG.new $ALERT_LOG

is done, you can lose any new events which would have occured between the tail and mv.

 

 

the role of the dd  is to get an extract begining at offset PREVSIZE

bs=$PREVSIZE means you set a buffer size to that value, and skip=1 means you skip the first buffer.

 

the tail is to cut 1000 lines from the file and keep only them.

 

now  I think a better way to do it would be:

1) first calculate PREVSIZE ( 0 if the file doesn't exist)

2) if PREVSIZE is larger than MAXSIZE, move ALERT_LOG to ALERT_LOG.old  and

       remove $ALERT_LOG.prev, and set NEWFILE=$ALERT_LOG.old

else

    copy ALERT_LOG to ALERT_LOG.prev and set NEWFILE to $ALERT_LOG.prev

3) if PREVSIZE=0   then CHECK_FILE=$NEWFILE

else

   extract with dd from NEWFILE to CHECK_FILE=/tmp/alert.log

 

4) grep on CHECK_FILE and mail

 

Like that, no event can be missed since we are always checking on a static file created atomically with the mv or the cp.

Also when the file reach the limit, it is moved to .old ( only atomical operation we can make to avoid to lose messages

when cutting the file.

- there is still a narrow window when we can miss to parse a line, it is when a write is made by oracle to the file while  we move the file, and flush only after the grep, but the window is much smaller than previously.