You are not logged in.

#1 2010-07-13 17:42:31

gazj
Member
From: /home/gazj -> /uk/cambs
Registered: 2007-02-09
Posts: 681
Website

Grep help needed in my script

I am writing a script that will watch everything.log, then eventually will pipe it's output to dzen2.  Here is my script so far.

gary@Lister ~ $ cat .bin/alerts 
#!/bin/bash

log()
{
tail -n 1 /var/log/messages.log
}

while true; do
if [ `log | grep -E 'mounted /dev/sdd' -c` -ge 1 ]; then 
    MESG="xd card mounted"
elif [ `log | grep -E 'unmounted /dev/sdd' -c` -ge 1 ]; then 
    MESG="xd card unmounted"
fi

echo $MESG
done

You can probably see my grep problem the first if line matches mounted and unmounted lines.  Damm.  I'm sure you guys can help a guy who struggles with bash put this one to rest wink

Offline

#2 2010-07-13 18:00:14

brisbin33
Member
From: boston, ma
Registered: 2008-07-24
Posts: 1,799
Website

Re: Grep help needed in my script

you could make your grep more specific, match on '^mounted' or ' mounted' so you don't catch 'unmounted' as well.

but the smarter way is probably to just reverse your if statement.  check for 'unmounted' first, that'll fail on just 'mounted' which would be caught in the elif.

i'd also recommend -qF for this:

#!/bin/bash

log() { tail -n 1 /whatever; }

while true; do
  # i'll put the sleep up top so i can just use `continue` when
  # our hook does catch and it'll still wait before checking again
  sleep 1

  if log | grep -qF 'unmounted /dev/whatever'; then
    echo 'your message'
    continue
  fi

  if log | grep -qF 'mounted /dev/whatever'; then
    echo 'your other message'
    continue
  fi

  # do you need to echo something in the no match case? might
  # be required for dzen, i dunno... if not, you can just remove this
  # and the redundant `continue` from the second if statement
  echo ' '
done

this could probably be refactored a couple different ways for efficiency (for instance, to read the log file only once, etc) but ill leave it close to your original for now smile

Offline

#3 2010-07-13 18:03:25

falconindy
Developer
From: New York, USA
Registered: 2009-10-22
Posts: 4,111
Website

Re: Grep help needed in my script

I would go about this a slightly different way. sed seems like a better solution, and there's no need to declare another function to repeatedly call tail on the log.

#!/bin/bash

while read $line; do
  sed -n 's,.*\(mounted|unmounted\) /dev/sdd.*,xd card \1,p' <<< "$line"
done < <(inotail -f -n 1 /var/log/everything.log)

I've used inotail instead of tail as its a far better log watcher (uses inotify rather than relying on a buffered output). tail can be safely substituted if you're not interested.

edit: is the while loop even necessary here? With (ino)tail blocking indefinitely while its waiting on data, would something as stupidly simple as 'inotail -f -n 1 /var/log/foo.log | sed ......' be effective?

Last edited by falconindy (2010-07-13 20:46:28)

Offline

#4 2010-07-13 18:13:00

gazj
Member
From: /home/gazj -> /uk/cambs
Registered: 2007-02-09
Posts: 681
Website

Re: Grep help needed in my script

I have learned how to shorten functions to one line. wink

Why do I seem to think I need [ ]'s on my if line's?

I guess grep when finds something returns a "true" so to speak when used in if this way.  Much better than counting the words matched like I did.  False returned with no match?

Echoing nothing seems like a good idea, as my last message will never disappear.


I had thought of reversing my if's but thought it to be unclean, but maybe the most simple way is the cleanest smile

Thanks

Last edited by gazj (2010-07-13 18:17:30)

Offline

#5 2010-07-13 18:14:40

gazj
Member
From: /home/gazj -> /uk/cambs
Registered: 2007-02-09
Posts: 681
Website

Re: Grep help needed in my script

falconindy wrote:

I would go about this a slightly different way. sed seems like a better solution, and there's no need to declare another function to repeatedly call tail on the log.

#!/bin/bash

while read $line; do
  sed -n 's|.*\(mounted|unmounted\) /dev/sdd.*|xd card \1|p' <<< "$line"
done < <(inotail -f -n 1 /var/log/everything.log)

I've used inotail instead of tail as its a far better log watcher (uses inotify rather than relying on a buffered output). tail can be safely substituted if you're not interested.

edit: is the while loop even necessary here? With (ino)tail blocking indefinitely while its waiting on data, would something as stupidly simple as 'inotail -f -n 1 /var/log/foo.log | sed ......' be effective?

I knew a 1 or 2 liner would come along which I totally would struggle to understand.  I need to walk before I can run wink

I do appreciate both your answers though smile

Offline

#6 2010-07-13 18:48:10

karol
Archivist
Registered: 2009-05-06
Posts: 25,440

Re: Grep help needed in my script

I'm not sure if this would be helpfull, but:

usm () {
DRIVE="/dev/sdb1"

if mount | grep -q $DRIVE; then
  umount $DRIVE
else
  mount -o rw,noauto,async,user,umask=1000 $DRIVE /mnt/usb
fi;
}

I use it to mount my usb drive. Of course you can use

echo 'your other message'

instead of the mount / unmount ones I have.

Offline

#7 2010-07-13 20:11:44

brisbin33
Member
From: boston, ma
Registered: 2008-07-24
Posts: 1,799
Website

Re: Grep help needed in my script

gazj wrote:

Why do I seem to think I need [ ]'s on my if line's?

all you need between the 'if' and the '; then' is an exit status. 

'[' is just another command (note that '[[' is a bash built-in that act very similarly); it will just give you that exit status depending how all the stuff before the final ']' evaluates.

knowing this...

gazj wrote:

I guess grep when finds something returns a "true" so to speak when used in if this way.  Much better than counting the words matched like I did.  False returned with no match?

grep -q is quiet so it won't show your matches (you only need to know that they were there, not what they were).  grep considers no-match a failure case and exits 1 (and 0 on match), so putting that directly in the if is just fine.

armed with this, you can even do simple error handling like this:

if ! wget www.something.com; then 
  # put any code here that should run in the case of a 
  # failed download
fi

Last edited by brisbin33 (2010-07-13 20:13:00)

Offline

#8 2010-07-13 22:20:47

gazj
Member
From: /home/gazj -> /uk/cambs
Registered: 2007-02-09
Posts: 681
Website

Re: Grep help needed in my script

Thanks brisbin.  I think I got it.  I still find bash syntax very hard.  It must be because I am older now.  When I was young I picked up basic so easily.

Offline

#9 2010-07-14 04:55:47

steve___
Member
Registered: 2008-02-24
Posts: 452

Re: Grep help needed in my script

falconindy wrote:

I've used inotail instead of tail as its a far better log watcher (uses inotify rather than relying on a buffered output).

Here[1] it says "As of version 7.5 of coreutils tail --follow uses inotify if available (as inotail does)."

[1] http://distanz.ch/inotail/

Offline

Board footer

Powered by FluxBB