askaquestion
askaquestion

Reputation: 151

tail and grep log and mail (linux)

i want to tail log file with grep and sent it via mail like:

tail -f /var/log/foo.log | grep error | mail -s subject [email protected]

how can i do this?

Upvotes: 11

Views: 23481

Answers (4)

ESP32
ESP32

Reputation: 8713

I use a 1-liner in my cronjob running every 60 minutes, checking if the file has changed within the last 60 minutes. If so, the last 3 lines of the log file are sent to me.

log_file=$(find /var/log/mylog.log -mmin -60) && [[ -n "$log_file" ]] && tail -n 3 "$log_file" | mail -s "Alert mylog" [email protected]

If you want to send the last 3 lines containing the word "ERROR", like requested by the op, you can modify this as follows:

log_file=$(find /var/log/mylog.log -mmin -60) && [[ -n "$log_file" ]] && grep "ERROR" "$log_file" | tail -n 3 | mail -s "Alert mylog" [email protected]

Upvotes: 0

user10969262
user10969262

Reputation: 1

How about:

mail -s "catalina.out errors" [email protected] < grep ERROR catalina.out

Upvotes: 0

Marcus Borkenhagen
Marcus Borkenhagen

Reputation: 6656

You want to send an email when emailing errors occur? That might fail ;)

You can however try something like this:

tail -f $log |
grep --line-buffered error |
while read line
do
    echo "$line" | mail -s subject "$email"
done

Which for every line in the grep output sends an email.

Run above shell script with

nohup ./monitor.sh &

so it will keep running in the background.

Upvotes: 23

micans
micans

Reputation: 1116

I'll have a go at this. Perhaps I'll learn something if my icky bash code gets scrutinised. There is a chance there are already a gazillion solutions to do this, but I am not going to find out, as I am sure you have trawled the depths and widths of the cyberocean. It sounds like what you want can be separated into two bits: 1) at regular intervals obtain the 'latest tail' of the file, 2) if the latest tail actually exists, send it by e-mail. For the regular intervals in 1), use cron. For obtaining the latest tail in 2), you'll have to keep track of the file size. The bash script below does that - it's a solution to 2) that can be invoked by cron. It uses the cached file size to compute the chunk of the file it needs to mail. Note that for a file myfile another file .offset.myfile is created. Also, the script does not allow path components in the file name. Rewrite, or fix it in the invocation [e.g. (cd /foo/bar && segtail.sh zut), assuming it is called segtail.sh ].

#!/usr/local/bin/bash
file=$1
size=0
offset=0
if [[ $file =~ / ]]; then
   echo "$0 does not accept path components in the file name" 2>&1
   exit 1
fi
if [[ -e .offset.$file ]]; then
   offset=$(<".offset.$file")
   fi
if [[ -e $file ]]; then
   size=$(stat -c "%s" "$file")    # this assumes GNU stat, possibly present as gstat. CHECK!
                                   # (gstat can also be Ganglias Status tool - careful).
fi
if (( $size < $offset )); then     # file might have been reduced in size
   echo "reset offset to zero" 2>&1
   offset=0
fi
echo $size > ".offset.$file"
if [[ -e $file &&  $size -gt $offset ]]; then
   tail -c +$(($offset+1)) "$file" | head -c $(($size - $offset)) | mail -s "tail $file" foo@bar
fi

Upvotes: 2

Related Questions