LinuxQuestions.org
Visit the LQ Articles and Editorials section
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 06-27-2008, 02:40 PM   #1
sfcg
LQ Newbie
 
Registered: Jun 2008
Posts: 5

Rep: Reputation: 0
Shell script to grep log for a specific error


First off I have written few shell scripts in my life, so I'm at the hello world level, just FYI.

I'm trying to write a script that greps the logs for a specific error and compares the date of that error to the current date. If the date is equal to or greater than the current date, I want it to email me.

Now I know my syntax is probably completely off, but I figured I'd post it somewhere to see if it was easily modified.

Thanks for taking the time to look at it.

Chris


#!/bin/bash
set A=`grep "ata1: command 0x25 timeout" /var/log/messages | awk '{print $2}'`
set B=`date | awk '{print $2}'`
if B=>A then
`cat /var/log/messages | egrep -e ata1 -e ata2 | mail -s "ATA errors on www5-sf" me@work.com`
endif
done
 
Old 06-27-2008, 03:56 PM   #2
Tinkster
Moderator
 
Registered: Apr 2002
Location: in a fallen world
Distribution: slackware by choice, others too :} ... android.
Posts: 22,986
Blog Entries: 11

Rep: Reputation: 880Reputation: 880Reputation: 880Reputation: 880Reputation: 880Reputation: 880Reputation: 880
What locale are you in, what do the outputs of date and the
date-format in messages look like?
 
Old 06-27-2008, 04:01 PM   #3
matthewg42
Senior Member
 
Registered: Oct 2003
Location: UK
Distribution: Kubuntu 12.10 (using awesome wm though)
Posts: 3,530

Rep: Reputation: 63
You can tell date what format to use for it's output. This is a little less cumbersome that post-processing the output with awk. If you use the same format string as the one found in the log file, you can just use grep to find matches for that day which contain some string.

There are a couple of ways to make the grep statement. Firstly, you can grep the logfile for all messages on the specified date, and then pipe that output into a second grep statement which can filter for the string you are looking for.

By the way $(this) does the same execute-and-use-result substitution as backticks, like `this`. I prefer $(this) because backticks are frequently mis-read, and are not nestable.

Assuming you are interested in today's log messages, you can do it like this:
Code:
grep "^$(date '+%b %e')" /var/log/messages |grep "ata1: command 0x25 timeout"
Note the meaning of %b and %e are documented in the date manual page. %b means the three letter month name abbreviation, and %e means the space padded day of the month.

A second method is to construct a pattern for grep which filters for both the date and the log text of interest. To understand it, you need to know a little about how regular expression patterns work. The "." character in regular expressions means "any character". The "*" character means "the previous expression zero or mor times". Thus you can use ".*" to mean "any combination of characters, or no characters at all". By the way "^", as used in the first solution means "the start of the line".

With this knowledge, you can make an expression which included both the required date filter, and the message pattern:
Code:
grep "^$(date '+%b %e').*ata1: command 0x25 timeout" /var/log/messages
This solution is arguably preferable to the first one in that it invokes only one process (a single grep, as opposed to two instances of grep). As a rule of thumb when shell scripting, the less processes you invoke, the better.
 
Old 06-27-2008, 04:38 PM   #4
sfcg
LQ Newbie
 
Registered: Jun 2008
Posts: 5

Original Poster
Rep: Reputation: 0
Matthewg42: Thank you. The expression is much more graceful then what I was trying to do. Now my next question is how would I use that as a trigger for the email requirement? It's been quite a while since I did any scripting or wrote an code at all, that my mid is stuck on using variables for this purpose when I know there must be a better way.

i.e.

#!/bin/bash
set A=$(grep "^$(date '+%b %e').*ata1: command 0x25 timeout" /var/log/messages)
if A="" then
end
else
mail -s "ATA error check" chris@work < $A

Unfortunately my knowledge of shell scriting syntax is limited, but my goal is to have it run through that expression and if it doesn't find anything it just ends. If it does, it emails the error.

I'm planning on brushing up on my shell scripting this weekend.

Thanks again.

Chris
 
Old 06-27-2008, 04:41 PM   #5
sfcg
LQ Newbie
 
Registered: Jun 2008
Posts: 5

Original Poster
Rep: Reputation: 0
Tinkster, I'm U.S. Pacific Standard Time

The output of the two variables are just simple integers i.e.

the set A is:

23
23
25
25


The set B is:

27


Thanks,

Chris
 
Old 06-27-2008, 04:57 PM   #6
matthewg42
Senior Member
 
Registered: Oct 2003
Location: UK
Distribution: Kubuntu 12.10 (using awesome wm though)
Posts: 3,530

Rep: Reputation: 63
grep will set the error level ($?) to 0 if a match was found, so you can test that:

Code:
a=$(grep "^$(date '+%b %e').*ata1: command 0x25 timeout" /var/log/messages)
if [ $? -eq 0 ]; then
    echo "$a" |mail -s "ATA error check found output" chris@work
fi
Here's were the nestable capability of the $() syntax is useful. If you used backticks it would not work.
 
Old 06-27-2008, 05:47 PM   #7
sfcg
LQ Newbie
 
Registered: Jun 2008
Posts: 5

Original Poster
Rep: Reputation: 0
Matthewg42:

Thanks again. I'll try this tonight after hours. Unfortunately can't fiddle with production right now.
 
Old 06-28-2008, 12:04 AM   #8
Mr. C.
Senior Member
 
Registered: Jun 2008
Posts: 2,529

Rep: Reputation: 59
Check out logcheck. It was built to do precisely what you are looking for.
 
Old 06-28-2008, 09:12 AM   #9
ghostdog74
Senior Member
 
Registered: Aug 2006
Posts: 2,696
Blog Entries: 5

Rep: Reputation: 241Reputation: 241Reputation: 241
awk ?
Code:
awk 'BEGIN {
 now=systime()
 FS="[: ]+"
 d="Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec"
 m=split(d,mon,"|")
 for(j=1;j<=m;j++) {
   month[mon[j]]=j
 }
}
FNR==NR && /ata1: command 0x25 timeout/{  
  t=mktime("2008 " month[$1]" "$2" "$3" "$4" "$5) 
  if ( t > now ) {
   flag=1
  }  
  next
}
flag && /ata[12]/{
  s=sprintf("%s\n",$0) s 
}
END{
 print s |"mail root"  
}

' /var/log/messages /var/log/messages
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Shell script with grep MicahCarrick Programming 4 08-15-2006 01:08 PM
shell script: grep using string with specail charactors? Chowroc Programming 6 11-14-2005 08:47 PM
Grep Syslog - email shell script voodoofxz Linux - Newbie 1 09-06-2005 04:27 PM
grep in shell script fails on redhat 3.0 rlangsto Linux - General 4 03-06-2005 07:42 PM
How do I zip and attach the output data of a grep | awk | mail shell script? 360 Programming 1 05-08-2002 08:26 AM


All times are GMT -5. The time now is 07:29 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration