X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=syslog-count-link.pl;h=c78ee402c2fe6a0dde14778b0714c8a74bff81cb;hb=f9fe79479e3a8845f472e0804c6b467c3431df59;hp=de1266de2ecbb5a6961d7f3f2effad9e39e80b96;hpb=928f02214443bf480e0e5c3872392a3302172b22;p=dell-switch diff --git a/syslog-count-link.pl b/syslog-count-link.pl index de1266d..c78ee40 100755 --- a/syslog-count-link.pl +++ b/syslog-count-link.pl @@ -2,52 +2,144 @@ use warnings; use strict; +# count Dell and Microtik syslog for port and stp events + +## report all logs: +# sudo cat /var/log/switch/sw-[a-z][0-9]*.log | ./syslog-count-link.pl | less -S +# +## tail logs and report status on kill -HUP +# sudo tail -f /var/log/switch/sw-[a-z][0-9]*.log | ./syslog-count-link.pl & + use Data::Dump qw(dump); +use POSIX qw(strftime); + +my $timeout = $ENV{TIMEOUT} || 60; # forget switch after sec +# timeout should be smaller than stp refresh inverval or +# stp messages will accumulate forever + +my $name = $0; +$name =~ s/.*\/([^\/]+)$/$1/; +$name =~ s/\.pl$//; +my $dir = "/dev/shm/$name"; +mkdir $dir unless -e $dir; + +our $stat; + +sub print_stats { + open(my $fh, '>', "$dir/stats"); + + foreach my $host ( sort keys %$stat ) { + foreach my $port ( sort { + my $a1 = $a; $a1 =~ s/\D+//g; + my $b1 = $b; $b1 =~ s/\D+//g; + no warnings; + $a1 <=> $b1; + } keys %{ $stat->{$host} } ) { + next if $port =~ m/^_/; + my $dt = time() - $stat->{$host}->{$port}->[0]; + if ( $dt > $timeout ) { + delete $stat->{$host}->{$port}; + next; + } + my $out = sprintf "%-12s %-8s %-2d %s\n", $host, $port, $dt, $stat->{$host}->{$port}->[1]; + print $out; + print $fh $out; + } + } + + close($fh); +} + +sub reset_stats { + if ( -e "$dir/reset" && unlink "$dir/reset" ) { + $stat = {}; + warn "# reset stats\n"; + } +} + + +$SIG{HUP} = sub { + print_stats(); + reset_stats; +}; + +warn "kill -HUP $$ # to dump stats\n"; +{ + open(my $fh, '>', "$dir/pid"); + print $fh $$; + close($fh); +} + +sub stat_host_port { + my ( $host, $port, $state ) = @_; + if ( ! exists $stat->{$host}->{$port} ) { + $stat->{$host}->{$port} = [-1, $state]; + } else { + $stat->{$host}->{$port}->[1] .= $state; + } + $stat->{$host}->{$port}->[0] = time(); + #warn "# stat_host_port ",dump($stat); +} -my $stat; my $host_re = '[\w-]+'; my $port_re = '[\w/]+'; while(<>) { chomp; + s/[\r\n]+//; + + reset_stats; - ## Dell + next if m/^$/; + next if m/%PIX-/; # ignore PIX logs + + ## Dell old if ( m/(\S+)\s%LINK-[IW]-(\w+):\s*(\w+)/ ) { my ($host,$state,$port) = ($1,$2,$3); - $stat->{$host}->{$port} .= substr($state,0,1); - $stat->{$host}->{_count}->{$port} += $state =~ m/Up/ ? 1 : -1; - } elsif ( m/(\S+)\s%STP-W-PORTSTATUS:\s([\w\/]+): STP status (\w+)/ ) { - my ($host,$port,$state) = ($1,$2,$3); - $stat->{$host}->{$port} .= '-'; - $stat->{$host}->{_count}->{$port} += $state =~ m/F/ ? 1 : -1; + stat_host_port( $host, $port, substr($state,0,1) ); + } elsif ( m/(\S+)\s%STP-W-PORTSTATUS:\s([\w\/]+)(?: of instance \d+)?: STP status (\w+)/ ) { + my ($host,$port,$state) = ($1,$2,substr($3,0,1) ); + stat_host_port( $host, $port, $state =~ m/f/i ? '-' : $state ); - ## Mikrotik + ## Dell new } elsif ( m/LINK - (\w+) - Hostname: <($host_re)>, ($port_re)/ ) { my ($state, $host, $port ) = ($1,$2,$3); - $stat->{$host}->{$port} .= substr($state,0,1); - $stat->{$host}->{_count}->{$port} += $state =~ m/U/ ? 1 : -1; + stat_host_port( $host, $port, substr($state,0,1) ); } elsif ( m/STP - PORTSTATUS - Hostname: <($host_re)>,($port_re): STP status (\w+)/ ) { my ($host,$port,$state) = ($1,$2,$3); - $stat->{$host}->{$port} .= '-'; - $stat->{$host}->{_count}->{$port} += $state =~ m/F/ ? 1 : -1; + stat_host_port( $host, $port, '-' ); + + + ## Mikrotik + } elsif ( m/($host_re) \w+: ([\w\-]+) link (\w+)/ ) { + my ($host, $port, $state ) = ($1,$2,$3); + stat_host_port( $host, $port, substr($state,0,1) ); + } elsif ( m/($host_re) TRAPMGR.* %% Spanning Tree Topology Change: (\d+)/ ) { + my ( $host, $state ) = ( $1, $2 ); + stat_host_port( $host, 'STP', $2 ); + + + } elsif ( m'==> /var/log/' ) { + # ignore tail output + next; } else { warn "IGNORE: [$_]\n"; + next; + } + + if ( -e "$dir/dump" || $ENV{DUMP} ) { + print "### ",strftime("%Y-%m-%d %H:%M:%S",localtime(time)), "\n"; + print_stats; } } + + warn "# stat = ", dump($stat); +print_stats; + -foreach my $host ( sort keys %$stat ) { - foreach my $port ( sort { - my $a1 = $a; $a1 =~ s/\D+//g; - my $b1 = $b; $b1 =~ s/\D+//g; - $a1 <=> $b1; - } keys %{ $stat->{$host} } ) { - next if $port =~ m/^_/; - printf "%s %s:%s %d\n", $host, $port, $stat->{$host}->{$port}, $stat->{$host}->{_count}->{$port}; - } -}