#!/bin/bash # # This script is supposed to be called periodically. # It goes through the last few lines of a logfile and counts some events. # The events are then reported to something. # # TODO: Also treat inbound email - maybe even accept things like proxy-accept and proxy-reject? # Debugging option #set -x # Go into appropriate directory cd `dirname $0` # Load configuration . ./settings.sh ### COUNTERS ### log_lines_total=0 log_lines_smtp=0 log_lines_smtpd=0 mo_sent=0 mo_deferred=0 mo_bounced_total=0 mo_bounced_spam=0 mo_bounced_reputation=0 mo_deliverable=0 mo_undeliverable=0 mi_accept=0 mi_reject=0 mi_proxy_accept=0 mi_proxy_reject=0 mi_connects=0 mi_connects_tls=0 ### First time setup (if required) if [ ! -f "$DBFILE" ]; then # Get initial log position new_log_position=$(wc -l $LOGFILE | cut -d ' ' -f 1) # Write initial log position echo $new_log_position > $DBFILE # Create rrd file rrdtool create $RRDFILE \ --start `date +%s` \ --step 60 \ DS:log_lines_total:GAUGE:60:0:U \ DS:log_lines_smtp:GAUGE:60:0:U \ DS:log_lines_smtpd:GAUGE:60:0:U \ DS:mo_sent:GAUGE:60:0:U \ DS:mo_deferred:GAUGE:60:0:U \ DS:mo_bounced_total:GAUGE:60:0:U \ DS:mo_bounced_spam:GAUGE:60:0:U \ DS:mo_bounced_reputation:GAUGE:60:0:U \ DS:mo_deliverable:GAUGE:60:0:U \ DS:mo_undeliverable:GAUGE:60:0:U \ DS:mi_accept:GAUGE:60:0:U \ DS:mi_reject:GAUGE:60:0:U \ DS:mi_proxy_accept:GAUGE:60:0:U \ DS:mi_proxy_reject:GAUGE:60:0:U \ DS:mi_connects:GAUGE:60:0:U \ DS:mi_connects_tls:GAUGE:60:0:U \ RRA:AVERAGE:0.5:1:1440 \ RRA:AVERAGE:0.5:15:1344 \ RRA:AVERAGE:0.5:30:720 \ RRA:AVERAGE:0.5:720:730 \ RRA:MAX:0.5:1:1440 \ RRA:MAX:0.5:15:1344 \ RRA:MAX:0.5:30:720 \ RRA:MAX:0.5:720:730 \ # Quick fix so rrdtool does not complain about updating too soon sleep 1 fi ### Action ### # Get old log position old_log_position=$(cat $DBFILE) # Get new log position new_log_position=$(wc -l $LOGFILE | cut -d ' ' -f 1) # Write new log position echo $new_log_position > $DBFILE # Get date for new log position db_last_modified=$(stat --terse $DBFILE | cut -d ' ' -f 13) # Make sure we do not have a log rotation going on # This is visible when old_log_position > new_log_position. if [ $new_log_position -lt $old_log_position ]; then # In this case, we set old_log_position to 0 old_log_position=0 fi # Collect number of log lines log_lines_total=`expr $new_log_position - $old_log_position` log_lines_smtp=$(sed -n "$old_log_position","$new_log_position"p $LOGFILE | grep '\/smtp\[' wc -l) log_lines_smtpd=$(sed -n "$old_log_position","$new_log_position"p $LOGFILE | grep '\/smtpd\[' wc -l) # Get lines and analyse them a bit, do the counting # Collect outbound email statistics - localhost is excluded. mo_sent=$( sed -n "$old_log_position","$new_log_position"p $LOGFILE | grep '\/smtp\[' | grep 'status=sent' | grep -v 'relay=127\.0\.0\.1\|relay=localhost\|relay=::1' | wc -l) mo_deferred=$( sed -n "$old_log_position","$new_log_position"p $LOGFILE | grep '\/smtp\[' | grep 'status=deferred' | grep -v 'relay=127\.0\.0\.1\|relay=localhost\|relay=::1' | wc -l) mo_deliverable=$( sed -n "$old_log_position","$new_log_position"p $LOGFILE | grep '\/smtp\[' | grep 'status=deliverable' | grep -v 'relay=127\.0\.0\.1\|relay=localhost\|relay=::1' | wc -l) mo_undeliverable=$( sed -n "$old_log_position","$new_log_position"p $LOGFILE | grep '\/smtp\[' | grep 'status=undeliverable' | grep -v 'relay=127\.0\.0\.1\|relay=localhost\|relay=::1' | wc -l) mo_bounced_total=$( sed -n "$old_log_position","$new_log_position"p $LOGFILE | grep '\/smtp\[' | grep 'status=bounced' | grep -v 'relay=127\.0\.0\.1\|relay=localhost\|relay=::1' | wc -l) mo_bounced_spam=$( sed -n "$old_log_position","$new_log_position"p $LOGFILE | grep '\/smtp\[' | grep 'status=bounced' | grep -i 'spam' | grep -v 'relay=127\.0\.0\.1\|relay=localhost\|relay=::1' | wc -l) mo_bounced_reputation=$(sed -n "$old_log_position","$new_log_position"p $LOGFILE | grep '\/smtp\[' | grep -i 'reputation' | grep -v 'relay=127\.0\.0\.1\|relay=localhost\|relay=::1' | wc -l) # Collect inbound email statistics mi_accept=$(sed -n "$old_log_position","$new_log_position"p $LOGFILE | grep '\/smtpd\[' | grep '\/smtpd\[' | grep ': [0-9A-F]*: client=' | wc -l) mi_reject=$(sed -n "$old_log_position","$new_log_position"p $LOGFILE | grep '\/smtpd\[' | grep ': NOQUEUE: reject:' | wc -l) mi_proxy_accept=$(sed -n "$old_log_position","$new_log_position"p $LOGFILE | grep '\/smtp\[' | grep ': proxy-accept: END-OF-MESSAGE: ' | wc -l) mi_proxy_reject=$(sed -n "$old_log_position","$new_log_position"p $LOGFILE | grep '\/smtp\[' | grep ': proxy-reject: END-OF-MESSAGE: ' | wc -l) # Collect connection data mi_connects=$(sed -n "$old_log_position","$new_log_position"p $LOGFILE | grep '\/smtpd\[' | grep ': connect from' | wc -l) mi_connects_tls=$(sed -n "$old_log_position","$new_log_position"p $LOGFILE | grep '\/smtpd\[' | grep 'Anonymous TLS connection established from' | wc -l) # Report counter results rrdtool update $RRDFILE \ -t log_lines_total:log_lines_smtp:log_lines_smtpd:mo_sent:mo_deferred:mo_bounced_total:mo_bounced_spam:mo_bounced_reputation:mo_deliverable:mo_undeliverable:mi_accept:mi_reject:mi_proxy_accept:mi_proxy_reject:mi_connects:mi_connects_tls \ $db_last_modified:$log_lines_total:$log_lines_smtp:$log_lines_smtpd:$mo_sent:$mo_deferred:$mo_bounced_total:$mo_bounced_spam:$mo_bounced_reputation:$mo_deliverable:$mo_undeliverable:$mi_accept:$mi_reject:$mi_proxy_accept:$mi_proxy_reject:$mi_connects:$mi_connects_tls # That's it. exit 0