#!/usr/bin/perl -l ## update the round robin database use strict; use warnings; use IO::File; use Time::Local; my @PORTS = qw ( 22 25 80 119 443 ); my $LAST = `rrdtool last /var/lib/rrd/tcp_services.rrd`; chomp $LAST; my $fh = IO::File->new('/var/log/iptraf/tcp_udp_services-eth0.log') or die "Can't open logfile"; while (<$fh>) { if ( m/service monitor started/ ) { _reset( $_ ); } next unless ( m/^\*\*\*/ ); my $hash = _parse( $_, $fh ); _update( $hash ) if ( $hash ); } ## translate iptraf's time string into unixtime sub _get_time { my ($input) = @_; my ($day, $month, $date, $hour, $minute, $second, $year) = split( /\s+|:/, $input ); $month = $month eq 'Jan' ? 0 : $month eq 'Feb' ? 1 : $month eq 'Mar' ? 2 : $month eq 'Apr' ? 3 : $month eq 'May' ? 4 : $month eq 'Jun' ? 5 : $month eq 'Jul' ? 6 : $month eq 'Aug' ? 7 : $month eq 'Sep' ? 8 : $month eq 'Oct' ? 9 : $month eq 'Nov' ? 10 : $month eq 'Dec' ? 11 : undef; die "Bad date $input" unless defined ( $month ); return timelocal( $second, $minute, $hour, $date, $month, $year ); } ## parse the log to the end. small race condition if we start reading ## log file while iptraf is writing? sub _parse { my ($header, $fh) = @_; my %hash; $hash{_time} = _get_time( ($header =~ m/generated (.*)/)[0] ); return unless $hash{_time} > $LAST + 60; while (<$fh>) { last if ( m/^Running/ ); next if ( m/^\s*$/ ); ## read data for tcp packets my ($proto) = $_ =~ m/^([^\/]+)/; next unless $proto eq 'TCP'; my ($port, $packs, $bytes, $rate, $pack_in, $byte_in, $rate_in, $pack_out, $byte_out, $rate_out) = $_ =~ m/([\d\.]+)/g; $hash{$port} = [$byte_in, $byte_out]; } return \%hash; } ## iptraf has restarted, put 'U' (unknown) in db. sub _reset { my ($line) = @_; my %hash; $hash{_time} = _get_time( (split( /;/, $line))[0] ); _update( \%hash ); } ## send update to the db sub _update { my ($hash) = @_; return unless $hash->{_time} > $LAST + 60; system( "/usr/bin/rrdtool", "update", "/var/lib/rrd/tcp_services.rrd", join(":", $hash->{_time}, map { ref($hash->{$_}) ? @{$hash->{$_}} : qw( U U ) } @PORTS ) ); }