Reputation: 151
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
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
Reputation: 1
How about:
mail -s "catalina.out errors" [email protected] < grep ERROR catalina.out
Upvotes: 0
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
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