monitor log entries and send e-mail

I am stuck and worried. My assignment was due a day ago and I was too busy completing other assignments due during the same time. I worry that not completing this assignment will fail me. Need urgent help in completing the script asap. I dont want to sound pushy to get the answer but just wanted to explain the situation.

  1. The problem statement, all variables and given/known data:

I have mentioned a detailed requirement to be very clear. The points with '*' are the tasks that the script is
expected to do. All other information provided is for clear understanding of the script functionality.

The basic form of the script will simply send a copy of all lines that contain either "error" or "warning"
to the user specified in the script as RECIPIENT. Note that RECIPIENT is a shell variable that will contain
an e-mail address.
The basic script will be able to look at a log file periodically and report on any new lines that contain
either "error" or "warning". The search for this text is to be "case insensitive". This means that the script
needs to accept a line containing either "error", "Error", "ERROR" or the word error spelt in any other
combination of upper and lower case letters as being functionally equivalent.

The basic script, named "logmon" (for log monitor) will need to do the following:

  • be able to run in an environment that does not include a path. (i.e. the environment provided by
    cron)

  • accept the name of a log file as the sole command line argument

  • search the specified log file for lines that have been added since the previous search.

  • construct an e-mail reporting any lines that contain either "error" or "warning" in any combination
    of upper and lower case letters

  • send the e-mail to the address specified in the RECIPIENT shell variable which is defined within the
    script

Optional requirements for now
Include only putting a single copy of a message in an e-mail, but reporting
how many times the message is repeated. Also modifying the script so that the same script will either
report via e-mail, or directly to a terminal, depending on how it is called. The final option will
be a system that reports errors directly to the root console.
(Note that this will need to be implemented in a way that sends the message to your account and does not actually send a message to root for testing purpose.)

Please add a comment or comments in your script that state which, if any, of the optional requirements have been implemented.

  • modify the script so that, instead of listing multiple lines with the same message, it lists one instance
    of each duplicated line (Note that for the purposes of this requirement, two lines that share everything
    except the timestamp are considered to be identical lines.)

  • follows the single instance of a duplicated line with a line that reports how many times the previous
    line repeats

  • add code that will report the above to the command line when it is called with the name "logcheck"
    (How could you have one script that has two different names?)

Note that any data that needs to be passed from one time when the script runs to the next time cannot be passed in a temporary file. It will
need to be stored in a secure location.

Certain commands that I thought might be helpful are diff, wc, tail, grep, awk, and sort. Can anyone think of a way to do the above. Any suggestions
are most welcome.
Thanks in Advance for all the help.

  1. Relevant commands, code, scripts, algorithms:

Algorithm of the program that I have come up with
Step1: Enter Logname(name of log file) as argument when running script
Step2: Check if argument is given, if not then exit with error else check for filename
Step3: If filename given as argument does not exists, exit with error else check for search string pattern in log file
Step4: if string pattern found then copy log entry to a variable and temp file
Step5: Check for similar log entries ignoring date stamp
Step6: if similar log entry found, increment counter
Step7: if currently running script name is logmon then send email else send message to current terminal

  1. The attempts at a solution (include all code and scripts):
#!/bin/sh -x
#
#
#
PRINTF=/usr/bin/printf
GREP=/usr/bin/grep
TAIL=/usr/bin/tail
#To if log file to check has been given as argument when running the script
if [ $# -eq 0 ] ; then
   $PRINTF "%s: Need the name of the log that needs to be checked\n" $0
   $PRINTF $0 "\tis the name of the script you are running" #Just to display what is the script name
   $PRINTF $1 "\tis the name of the log file you want to scan" #Just to display what is the argument
   exit 1
fi
# script to send simple email
SUBJECT="Enter Subject Here" # email subject
RECIPIENT="yourmailid@domain.com" # Email To ?
EMAILMESSAGE="My test script" # Email text/message

/bin/mailx -s "$SUBJECT" "$RECIPIENT" < $EMAILMESSAGE # send an email using /bin/mail

# script to check for string to search
SEARCH='grep -i -E -q 'error|warning'' #search for strings error or warning in any form
SCAN_LOG='tail $1|[${SEACH}]'  #scanning logfile for string pattern



#Keep track of similar entries
MESSAGE_COUNTER=0
MESSAGE="$LOG_ENTRY"
  1. Complete Name of School (University), City (State), Country, Name of Professor, and Course Number (Link to Course):
    RMIT University, Melbourne,Australia,Don,Unix Essentials for System Administrators - RMIT University

Note: Without school/professor/course information, you will be banned if you post here! You must complete the entire template (not just parts of it).

---------- Post updated at 10:37 AM ---------- Previous update was at 10:11 AM ----------

The log file structure looks like below

Apr 26 03:18:54 goanna.cs.rmit.edu.au SRS Proxy[17590]: [ID 663108 daemon.error] Could not upload bulk message
Apr 26 03:21:25 goanna.cs.rmit.edu.au last message repeated 3 times
Apr 26 03:31:41 goanna.cs.rmit.edu.au puppetd[25496]: [ID 702911 daemon.notice] (//Node[server_base]/pca/File[/opt/isunix/output]) Dependency file[/var/tmp/patchdiag.xref] has 1 failures
Apr 26 03:31:41 goanna.cs.rmit.edu.au puppetd[25496]: [ID 702911 daemon.warning] (//Node[server_base]/pca/File[/opt/isunix/output]) Skipping because of failed dependencies
Apr 26 03:31:41 goanna.cs.rmit.edu.au puppetd[25496]: [ID 702911 daemon.notice] Finished catalog run in 134.93 seconds
Apr 26 03:40:55 goanna.cs.rmit.edu.au SRS Proxy[17590]: [ID 663108 daemon.error] Could not upload bulk message
Apr 26 03:44:40 goanna.cs.rmit.edu.au last message repeated 3 times
Apr 26 03:45:56 goanna.cs.rmit.edu.au SRS Proxy[17590]: [ID 388765 daemon.error] Could not send message from queue: /var/SUNWsrspx/SRSQueueStore/store/queues/REGISTRATION/registration
Apr 26 03:49:11 goanna.cs.rmit.edu.au SRS Proxy[17590]: [ID 663108 daemon.error] Could not upload bulk message
Apr 26 03:52:52 goanna.cs.rmit.edu.au SRS Proxy[17590]: [ID 601329 daemon.warning] QueueStore reclaimed 1 entry, 6144 bytes
Apr 26 04:05:59 goanna.cs.rmit.edu.au puppetd[25496]: [ID 702911 daemon.warning] (//Node[server_base]/pca/Exec[pca-generate-missingrs]) Skipping because of failed dependencies
Apr 26 04:05:59 goanna.cs.rmit.edu.au puppetd[25496]: [ID 702911 daemon.notice] (//Node[server_base]/pca/File[/opt/isunix/output]) Dependency file[/var/tmp/patchdiag.xref] has 1 failures
Apr 26 04:05:59 goanna.cs.rmit.edu.au puppetd[25496]: [ID 702911 daemon.warning] (//Node[server_base]/pca/File[/opt/isunix/output]) Skipping because of failed dependencies
Apr 26 04:06:00 goanna.cs.rmit.edu.au puppetd[25496]: [ID 702911 daemon.notice] Finished catalog run in 135.37 seconds
Apr 26 04:06:41 goanna.cs.rmit.edu.au SRS Proxy[17590]: [ID 663108 daemon.error] Could not upload bulk message
Apr 26 04:07:56 goanna.cs.rmit.edu.au SRS Proxy[17590]: [ID 388765 daemon.error] Could not send message from queue: /var/SUNWsrspx/SRSQueueStore/store/queues/REGISTRATION/registration
Apr 26 04:11:11 goanna.cs.rmit.edu.au SRS Proxy[17590]: [ID 663108 daemon.error] Could not upload bulk message
Apr 26 04:22:56 goanna.cs.rmit.edu.au SRS Proxy[17590]: [ID 663108 daemon.error] Could not upload bulk message
Apr 26 04:25:26 goanna.cs.rmit.edu.au last message repeated 2 times

---------- Post updated at 05:11 PM ---------- Previous update was at 10:37 AM ----------

If someone could help me out in rectifying the problem!!!

#!/bin/sh -x
#
#
#
PRINTF=/usr/bin/printf
GREP=/usr/bin/grep
TAIL=/usr/bin/tail
LOG_FILE="$1"
#To check if log file to check has been given as argument when running the script
if [ $# -ne 0 ] ; then
           $PRINTF "%s: Is the name of the log file you will be scanning. \n" $1
           $PRINTF $LOG_FILE"\n"

                if [ -f $LOG_FILE ];       #if logfile exits
                then
                        echo "File $LOG_FILE exists \n"

                        # script to check for string to search
                        SEARCH='grep -i -E -q 'error|warning'' #search for strings error or warning in any form
                        SCAN_LOG='tail $1|[${SEARCH}]'  #scanning logfile for string pattern

                        # script to send simple email
                        SUBJECT="Error/Warning messages in logfile" # email subject
                        RECIPIENT="emailid@domain.extension" # Email To ?
                        EMAILMESSAGE="SCAN_LOG" # Email text/message

                        /bin/mailx -s "$SUBJECT" "$RECIPIENT" < $EMAILMESSAGE # send an email using /bin/mail
                else
                        echo "File $LOG_FILE does not exists \n"
                fi

        else
           $PRINTF "%s: Need the name of the log that needs to be checked\n" $0
#       EXIT (1)
fi

The output that I got for the above code :

> sh logmon1 log-out
log-out: Is the name of the log file you will be scanning.
log-out
File log-out exists

logmon1: warning: not found
logmon1: SCAN_LOG: cannot open

Hi,

If I execute this statement on the command line, I get an error:

$ SEARCH='grep -i -E -q 'error|warning''
warning: command not found

You probably meant to use backticks (`) instead of quotes (')
This is sometimes difficult to see, that is why I prefer using $( ... ) instead of `...`
Also if you use grep you have give it something to grep (file or stdin)..

If you reference a variable you have to use a $-sign .

EMAILMESSAGE="$SCAN_LOG"
1 Like

Thanks for pointing that out.
I also noticed that none of the commands like GREP that i defined have $ in front of them. I have corrected them. I will update the code and post it up again. Code someone please help me out with this.. I am finding it very confusing to do the script. Its the first time that i am writing such a script. I have hardly 3 months of experience and that too only by completing labs sheets of my uni.

---------- Post updated at 09:01 PM ---------- Previous update was at 08:15 PM ----------

I have made some improvements from the previous code and rectified the wrongs notified, thanks to

The code now execute without any error but gets stuck and i have to suspend the script manually. I am not able to figure out what the problem is and how am i supposed the implement the logic. Please see code below. I have tried to highlight all new lines of code that i have added:

#!/bin/sh -x
#
#
#
PRINTF=/usr/bin/printf
GREP=/usr/bin/grep
TAIL=/usr/bin/tail
COPY=/usr/bin/cp
CAT=/usr/bin/cat
LOG_FILE="$1"
LOG_PATH="/var/log/$1"

#To check if log file to check has been given as argument when running the script
if [ $# -ne 0 ] ; then
           $PRINTF "%s: Is the name of the log file you will be scanning. \n" $1
           $PRINTF $LOG_FILE"\n"
           $PRINTF $LOG_PATH"\n"

                if [ -f $LOG_PATH ];       #if logfile exits
                then
                        echo "File $LOG_FILE exists \n"
                        $COPY $LOG_PATH ./
                        $CAT -n $LOG_FILE > ./tmp_log
#                       $CAT tmp_log | less

                        #SEARCH=`GREP -i -E -q 'error|warning' $LOG_PATH` #search for strings error or warning in any form
                        # script to check for string to search
                        SEARCH=`$GREP -i 'error|warning'` #search for strings error or warning in any form
#                        SCAN_LOG=`$TAIL $1|[${SEARCH}]`  #scanning logfile for string pattern

                        # script to send simple email
                        SUBJECT="Error/Warning messages in logfile" # email subject
                        RECIPIENT="emailid@domain.extension" # Email To ?
#                       EMAILMESSAGE="$SCAN_LOG" # Email text/message
                        EMAILMESSAGE="$SEARCH" # Email text/message

                        /bin/mailx -s "$SUBJECT" "$RECIPIENT" < $EMAILMESSAGE # send an email using /bin/mail
                                echo "mail sent"
                else
                        echo "File $LOG_FILE does not exists \n"
                fi

        else
   $PRINTF "%s: Need the name of the log that needs to be checked\n" $0
#       EXIT (1)
fi

"logmon1" 48 lines, 1420 characters

The output is this:

> sh logmon1 log.03
log.03: Is the name of the log file you will be  scanning.
log.03
/../../log.03
File log.03 exists

^C
>

Just to add. I also do not receive any e-mail message. Some one please help me here with the logic also. The requirements of the script is highlighted in blue in the original post.
Thanks in advance!!!

I found another problem:
The below command when given in command line gives output if the word error is there in the file

grep - i 'error' <filename> 
Apr 26 03:40:55 goanna.cs.rmit.edu.au SRS Proxy[17590]: [ID 663108 daemon.error] Could not upload bulk message
Apr 26 03:45:56 goanna.cs.rmit.edu.au SRS Proxy[17590]: [ID 388765 daemon.error] Could not send message from queue: /var/SUNWsrspx/SRSQueueStore/store/queues/REGISTRATION/registration
Apr 26 03:49:11 goanna.cs.rmit.edu.au SRS Proxy[17590]: [ID 663108 daemon.error] Could not upload bulk message

But this gives no output even if the string are present in the file that is being searched

grep -i 'error|warning' <filename> 
>

Hi Vin8465,

if you use grep you have give it something to grep (file or stdin)..
In this segment you do not specify the input file, so grep is waiting for input.

SEARCH=`$GREP -i 'error|warning'`
1 Like

So silly of me. But do you think the logic is alright. Any inputs on how should i go about completing the script functionality. I am learning all the commands as am doing the script, but i am already a day over the submission date and dont want to spend too much time trying to analyse what could be done.
I believe that self learning will be better for me in the long run and i intend to do the advanced course of the subject but i do need to submit this script asap so as to pass the subject. So am requesting the experts of the forum to help me out here.

---------- Post updated at 09:42 PM ---------- Previous update was at 09:35 PM ----------

I changed the line into

SEARCH=`$GREP -i 'error|warning' $1`

but the output seems to be the same.

> sh logmon1 log.03
log.03: Is the name of the log file you will be  scanning.
log.03
/../../log.03
File log.03 exists

^C
> 

I am not able to figure out why the script just keeps waiting. Is there a way to check what the script is waiting for?

You need to use egrep instead of grep...

1 Like

I too was trying that out. But you found it out before i could. There are no errors now and the script also seems to execute to completion.
Although everything seems to run to perfection, i dont receive any email. Is the command

SEARCH=`$EGREP -i 'error|warning' $1`

not storing the output to SEARCH?
When i run the script with the grep changed to egrep, i get the output in my terminal.
How should i redirect the output to SEARCH and then put it in the EMAILMESSAGE variable?

Hi, since $EMAILMESSAGE is a variable and not a file you can not use input redirection like that. Also it is typically good practice to quote variable references..
You could try:

echo "$EMAILMESSAGE" | /bin/mailx -s "$SUBJECT" "$RECIPIENT"

or better yet:

printf "%s\n" "$EMAILMESSAGE" | /bin/mailx -s "$SUBJECT" "$RECIPIENT"

Which would protect against awkward characters in the email message body.

Is $RECIPIENT set to a valid email address?

1 Like

Hey Scrutinizer,
You seem to live up to your display id.I have made the changes accordingly. And yes the e-mail id is set to a valid id. I recieved the mail with all the the messages that contain error or warning.
I will put up the updated code separately.
:b::b::b::b::b:
Could you also give me a hint on how i could do the tasks of script. The main task is to scan the log file for new entries. I am not able to figure out how to scan the log file for the first time and then when the script is run the 2nd time, it needs to scan only new entries and ignore previous entries.
My approach was to create a tmp_log file of the log that is being scanned and then read from there. But i then realized if a different log file is scanned every time then my approach would fail.
What is your opinion? Could you please give a logic and possible commands to use.
I might consider using wc for counting line numbers and then compare the logfile given asn argument with tmp_log that the script creates. then find the difference of the lines and print that in a second tmp_log file and do operations on that.

Again, Thanks for you valuable feebacks.

---------- Post updated at 11:08 PM ---------- Previous update was at 10:52 PM ----------

New improvements in the script are:
This script now searches for string mentioned searched using egrep.
Stores output of egrep in a variable and is passed to the email message variable.
It successfully sends an email with the entries of the specified log file that matched the string pattern in egrep
The code is below. I have tried to highlight all the recent updates that were made:

#!/bin/sh -x
#
#
#
PRINTF=/usr/bin/printf
EGREP=/usr/bin/egrep
TAIL=/usr/bin/tail
COPY=/usr/bin/cp
CAT=/usr/bin/cat
LOG_FILE="$1"
LOG_PATH="/var/log/$1"
#To check if log file to check has been given as argument when running the script
if [ $# -ne 0 ] ; then
           $PRINTF "%s: Is the name of the log file you will be scanning. \n" $1
           $PRINTF $LOG_FILE"\n"
           $PRINTF $LOG_PATH"\n"

                if [ -f $LOG_PATH ];       #if logfile exits
                then
                        echo "File $LOG_FILE exists \n"
                        $COPY $LOG_PATH ./  #create copy of original log file in current directory
                        $CAT -n $LOG_FILE > ./tmp_log #Store a copy of original log file in a temporary log file with number index

                        # script to check for string to search
                        SEARCH=`$EGREP -i 'error|warning' $1` #search for strings error or warning in any form
#                       SCAN_LOG=`$TAIL $1|[${SEARCH}]`  #scanning logfile for string pattern

                        # script to send simple email
                        SUBJECT="Error/Warning messages in logfile" # email subject
                        RECIPIENT="validmailid@domain.extension" # Email To ?
#                       EMAILMESSAGE="$SCAN_LOG" # Email text/message
                        EMAILMESSAGE="$SEARCH" # Email text/message
                        echo "mail not sent yet"
                        $PRINTF "%s\n" "$EMAILMESSAGE" | /bin/mailx -s "$SUBJECT" "$RECIPIENT"  #send email with subject message to specified mail id
                                echo "mail sent"
                else
                        echo "File $LOG_FILE does not exists \n"
                fi

        else
           $PRINTF "%s: Need the name of the log that needs to be checked\n" $0
#       EXIT (1)
fi

The output of the script now is as below:

> sh logmon1 log.04
log.04: Is the name of the log file you will be scanning.
log.04
/../../../../log.04
File log.04 exists

mail not sent yet
mail sent
>
1 Like

Hi pseudocoder,
you are right. But my main intention of putting the echo there was to check what line in the script has been executed so far. Also I need to figure out how nt to send a mail if nothing is found from the searched string pattern.

I still am trying to figure out how the script can be modified to monitor and report only new entries when it is run for the second time with the same log file as an argument.

---------- Post updated at 08:44 AM ---------- Previous update was at 08:42 AM ----------

:b:thanks for pointing that out. I will remember to take that out as it looks a bit misleading.

---------- Post updated at 01:36 PM ---------- Previous update was at 08:44 AM ----------

I have reformatted the code to suit the needs of the script task.
I have tried to highlight all the pieces of code that has been shifted, added or changed in blue.
All improvements required are highlighted in red. I have updated certain parts of the code and highlighted it using orange

#!/bin/sh -x
#
#
#############
#
#THE PURPOSE OF THIS SCRIPT 'logmon'?
#THE SCRIPT IS INTENDEED TO MONITOR LOG FILES AND REPORT ANY ENTRIES THAT CONTAIN THE PATTERN "ERROR" OR "WARNING" IN ANY FORMAT
#THE SCRIPT SENDS AN EMAIL TO THE ID MENTIONED IN THE RECIPIENT VARIABLE IF THE PATTERN IS FOUND. NOTE:- THE SCRIPT IS INTENDED 
#TO CHECK A LOG FILE COMPLETELY FOR THE FIRST TIME THE LOG FILE IS BEING SCANNED AND THEN CHECKS ONLY THE NEWLY ADDED LOG ENTRIES
#HENCEFORTH.
#
#############
#
#WHAT DOES THE SCRIPT REQUIRE TO EXECUTE?
#THIS SCRIPT TAKES AN ARGUMENT WHICH IS THE ABSOLUTE PATH WITH THE NAME OF THE FILE THAT YOU WISH TO SCAN.
#
############
#WHAT DOES MY SCRIPT DO SO FAR?
#IT CHECKS IF AN ARGUMENT IS PASSED WHEN THE SCRIPT IS BEING EXECUTED. IT EXITS OUT WITH AN ERROR MESSAGE
#IF THE ARGUMENT IS NOT GIVEN. WHEN THE SCRIPT IS GIVEN THE ABSOLUTE PATH OF THE FILE TO SCAN FOR STRING PATTERNS, IT FIRST GIVES
#INFORMATION OF WHICH FILE IS GOING TO BE SCANNED.
#FINALLY IT DISPLAYS A MESSAGE AFTER SENDING THE EMAIL TO THE ID MENTIONED IN THE RECIPIENT. 
#IF THE LOG FILE BEING SEARCHED IS NOT LOCATED IN THE PATH DISPLAYED EARLIER,IT DISPLAYS A FILE NOT FOUND MESSAGE AND EXITS THE SCRIPT
#THE FILE NOW CREATES A TEMPORARY FILE tmp_log WHICH BASICALLY IS A COPY OF THE LOG FILE BEING SCANNED. ANOTHER FILE diff_result IS CREATED WHICH
#CONTAINS UPDATED ENTRIES OF THE CURRENTLY SCANNED LOG FILE
#
############
#
#WHAT NEEDS TO BE DONE?
#LOGIC FOR SEARCHING ONLY UPDATED ENTRIES TO THE CURRENTLY SCANNED LOG FILE IS ALMOST DONE BUT REQUIRES TUNING.
#FIND HOW MANY TIMES A PARTICULAR ENTRY IS REPEATED TO GIVE LOGISTICS OF WHICH ERROR OCCURS HOW MANY TIMES.
#NOTE:- TIME STAMP IS TO BE IGNORED FOR THIS SCRIPT WHEN COMPARING DUPLICATE ENTRIES.
#
############

PRINTF=/usr/bin/printf
EGREP=/usr/bin/egrep
TAIL=/usr/bin/tail 
COPY=/usr/bin/cp
CAT=/usr/bin/cat
DIFF=/usr/bin/diff
LOG_FILE_PATH="$1"                 # should contain the absolute path of the file to be scanned
SEARCH=`$EGREP -i 'error|warning' $1`         #search for strings error or warning in any form
RECIPIENT="validmailid"     # Email To ?


#To check if log file to be scanned has been given as argument when running the script
if [ $# -ne 0 ] ; then
           $PRINTF "%s is the log file that will be read \n" $1

        if [ -f $1 ];       #check if log file exists
        then
               $PRINTF "File exists \n"


            # script to check for string to search
#            SCAN_LOG=`$TAIL $1|[${SEARCH}]`  #scanning logfile for string pattern

            # Here am trying to grab all the updated entries in the log file with the match pattern.
            # So far I am not able to figure out how to do so. I have commented it as it only grabs the last
            # few lines that were updated in the log file.

            # script to send simple email
            SUBJECT="Error/Warning messages in logfile" # email subject
#            EMAILMESSAGE="$SCAN_LOG" # Email text/message
            EMAILMESSAGE="$SEARCH" # Email text/message
                if [ -z "$SEARCH" ];  #Check if any value has been added to variable that will later be passed to EMAILMESSAGE variable. This is basically to avoid sending an e-mail if nothing was found in the log matching the search pattern
                then
                $PRINTF "There is no message to send \n"
                else
                $PRINTF "%s\n" "$EMAILMESSAGE" | /bin/mailx -s "$SUBJECT" "$RECIPIENT"  #send email with subject message to specified mail id 
                $PRINTF "Mail sent to %s" $RECIPIENT
                fi
                $DIFF -b $1 ./tmp_log > ./diff_result
                $COPY $1 ./tmp_log # To keep track of what is updated when this log file is scanned again
#Here am using diff to compare the entries updated in the current log which is being scanned with the tmp_log that contains the entries of log file before the script was run 
#through the log for the second time. I am still trying to perfect it. It basically outputs the result of diff in diff_result file and then I need to do a pattern match on that file
#to e-mail only newly updated entries of the log file.
        else
               $PRINTF "File %s  does not exist \n" $1
            $PRINTF "Please place log file to be scanned in the above mentioned path \n" 
        fi

else
$PRINTF "Script %s: needs the absolute path of the log that needs to be checked\n" $0
fi

I get the following error if the search pattern doesnt match. At least that that is what the problem according to me. The output of an unsuccessful run is as below:

sh logmon /var/log/syslog.0
/var/log/syslog.0 is the log file that will be read
File exists
logmon: test: argument expected

The output of a successful run is as below:

sh logmon /<dir>/<dir>/<dir>/log.01
/<dir>/<dir>/<dir>/log.01 is the log file that will be read
File exists
Mail sent to <validmailid>

I am not sure that the following code works as it should.

if [ -z $SEARCH ];
                then
                $PRINTF "There is no message to send \n"
                else
                $PRINTF "%s\n" "$EMAILMESSAGE" | /bin/mailx -s "$SUBJECT" "$RECIPIENT"  #send email with subject message to specified mail id 
                $PRINTF "Mail sent to %s" $RECIPIENT
                fi

---------- Post updated at 01:55 PM ---------- Previous update was at 01:36 PM ----------

Found the problem with the if statement. Changes are in blue

 if [ -z "$SEARCH" ];
                                then
                                $PRINTF "There is no message to send \n"
                                else
                                $PRINTF "%s\n" "$EMAILMESSAGE" | /bin/mailx -s "$SUBJECT" "$RECIPIENT"  #send email with subject message to specified mail id
                                $PRINTF "Mail sent to %s" $RECIPIENT
                                fi

The output now if the log file does not contain the string pattern is

sh logmon /var/log/syslog.0
/var/log/syslog.0 is the log file that will be read
File exists
There is no message to send

---------- Post updated at 06:05 PM ---------- Previous update was at 01:55 PM ----------

The script now basically works fine. Certain advanced requirements of the script task that i have not implemented are:

  1. If same script is renamed to logcheck then the reports the script generates should be displayed in the command line.
  2. Error messages that are repeated are to be counted and only one instance of error message is to be reported followed by the comment "The above message appeared n times"

Note: Time stamp is being ignored when making the above improvements. i.e a log entry having identical time stamps will not be considered when grouping messages.

The code is as below. I have reformatted the entire code, so have not highlighted parts of the code.

#!/bin/sh
#set -x
#
#
#############
#
#THE PURPOSE OF THIS SCRIPT 'logmon'?
#THE SCRIPT IS INTENDEED TO MONITOR LOG FILES AND REPORT ANY ENTRIES THAT CONTAIN THE PATTERN "ERROR" OR "WARNING" IN ANY FORMAT
#THE SCRIPT SENDS AN EMAIL TO THE ID MENTIONED IN THE RECIPIENT VARIABLE IF THE PATTERN IS FOUND.
# NOTE:- THE SCRIPT IS INTENDED TO CHECK A LOG FILE COMPLETELY WHEN IT IS SCANNED FOR THE FIRST TIME AND THEN CHECKS ONLY THE NEWLY ADDED LOG ENTRIES
#HENCEFORTH.
#
#############
#
#WHAT DOES THE SCRIPT REQUIRE TO EXECUTE?
#THIS SCRIPT TAKES AN ARGUMENT WHICH IS THE ABSOLUTE PATH WITH THE NAME OF THE FILE THAT YOU WISH TO SCAN.
#
############
#
#WHAT DOES MY SCRIPT DO SO FAR?
#IT CHECKS IF AN ARGUMENT IS PASSED WHEN THE SCRIPT IS BEING EXECUTED.
#IT EXITS OUT WITH AN ERROR MESSAGE IF THE ARGUMENT IS NOT GIVEN.
#ON PROPER EXECUTION, IT FIRST GIVES INFORMATION OF WHICH FILE IS GOING TO BE SCANNED.
#FINALLY IT DISPLAYS A MESSAGE  OF WHETHER AN E-MAIL WAS SENT OR NOT
#IF THE LOG FILE BEING SEARCHED IS NOT LOCATED IN THE PATH DISPLAYED EARLIER,IT DISPLAYS A FILE NOT FOUND MESSAGE AND EXITS THE SCRIPT
#NOTE: THE SCRIPT CHECKS WHETHER THE CURRENTLY SCANNED LOG FILE HAS BEEN PREVIOUSLY SCANNED OR NOT. IF NOT SCANNED A TMP_LOG FILE IS CREATED
#AND CONTENTS OF THE LOG FILE IS DUMPED INTO TMP_LOG. IF SCANNED PREVIOUSLY, THEN ALL UPDATED ENTRIES ARE PLACED IN A TEMPORARY FILE AND ONLY
#THOSE ENTRIES ARE CHECKED & REPORTED FOR THE SEARCH PATTERN
#
############
#
PRINTF=/usr/bin/printf
EGREP=/usr/bin/egrep
TAIL=/usr/bin/tail
COPY=/usr/bin/cp
CAT=/usr/bin/cat
DIFF=/usr/bin/diff
REMOVE=/usr/bin/rm
#LOG_FILE_PATH="$1"                             # should contain the absolute path of the file to be scanned
SEARCH=`$EGREP -i 'error|warning' $1`           #search for strings error or warning in any form
RECIPIENT="validmailid@domain.extension"        # Email To ?
SUBJECT="Error/Warning messages in logfile"     # email subject


if [ $# -ne 0 ] ;    #To check if log file to be scanned has been given as argument when running the script
then
           $PRINTF "%s is the log file that will be read \n" $1

                if [ -f $1 ];       #check if log file to be scanned exists
                then
                        $PRINTF "File exists \n"

                        if [ -f ./tmp_log ];     #To check if current log file was scanned for the first time
                        then

                                $DIFF -b $1 ./tmp_log > ./diff_result #Resource that contains only updated entries of the current log file
                                SEARCH_UPDATES_ONLY=`$EGREP -i 'error|warning' ./diff_result`
                                $REMOVE ./diff_result
                                EMAILMESSAGE="$SEARCH_UPDATES_ONLY" # Email text/message Contains log entries from diff_result
                                if [ -z "$SEARCH_UPDATES_ONLY" ];
                                then
                                        $PRINTF "There is no message to send \n"

                                else
                                        $PRINTF "%s\n" "$EMAILMESSAGE" | /bin/mailx -s "$SUBJECT" "$RECIPIENT"  #sends email of updated log entries that match the pattern
                                        $PRINTF "Mail sent to %s" $RECIPIENT
                                fi
                        else
                                EMAILMESSAGE="$SEARCH" # Email text/message #Contains log entries from actual log file
                                if [ -z "$SEARCH" ];
                                then
                                        $PRINTF "There is no message to send \n"
                                else
                                        $PRINTF "%s\n" "$EMAILMESSAGE" | /bin/mailx -s "$SUBJECT" "$RECIPIENT"  #send email with all log entries  that matche the search pattern
                                        $PRINTF "Mail sent to %s" $RECIPIENT
                                fi
                        fi
                        $COPY $1 ./tmp_log # To keep track of what is updated when this log file is scanned again
                else
                        $PRINTF "File %s  does not exist \n" $1
                        $PRINTF "Please place log file to be scanned in the above mentioned path \n"
                fi

else
        $PRINTF "Script %s: needs the absolute path of the log that needs to be checked\n" $0
fi

The output of a successful run will be as below depending on the situation:

 sh logmon /<dir>/<dir>/<dir>/log.01
/<dir>/<dir>/<dir>/log.01 is the log file that will be read
File exists
There is no message to send
 sh logmon /<dir>/<dir>/<dir>/log.01
/<dir>/<dir>/<dir>/log.01 is the log file that will be read
File exists
Mail sent to validmailid@domain.extension>

Could someone please help me with the advanced parts. I need urgent help to finish this script off today itself.