Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

socksumm -- Display a summary of open sockets

by grinder (Bishop)
on Sep 13, 2006 at 10:59 UTC ( #572712=sourcecode: print w/ replies, xml ) Need Help??

Category: Networking Code
Author/Contact Info grinder @ perlmonks
Description:

I've had this lying around for some time. It just takes the output of netstat and summarises the information la vmstat, iostat. I have used it for keeping an eye on large daemons that have shown a tendency to go mad.

I don't see that there's anything else to add to it, but I'd be interested in seeing if anyone has suggestions and ways it could be improved.

update: now with Win32 support! thanks Discipulus for the suggestion

#! /usr/bin/perl -w
#
# socksumm -- socket usage summary
#
# Copyright (C) 2005-2006 David Landgren

use strict;
use Getopt::Long;

my $VERSION = '1.1';

my $ok = GetOptions(
    'help',         \my $help,
    'localport=s',  \my $watch_local_port,
    'remoteport=s', \my $watch_remote_port,
    'port=s',       \my $watch_port,
    'sleep=i',      \my $sleep,
    'version',      \my $version,
    'num=i',        \my $num,
);

if( not $ok or $help ) {
    eval "use Pod::Usage";
    if( $@ ) {
        print <<HELP;
$0 [-localport=?] [-remoteport=?] [-port=?] [-sleep=n] [-num=n]
(install Pod::Usage for detailed help)
HELP
    }
    else {
        pod2usage(1);
    }
    exit;
}

$sleep ||= 60;

if( $version ) {
    eval "use File::Basename";
    print +($@ ? $0 : basename($0)), " v$VERSION\n";
    exit 0;
}

my $netstat_re;
my $args;

# platform-specific settings;
{
    my $ip_re = '\d+(?:\.\d+){3}';

    if( $^O eq 'freebsd' ) {
        $args = '-nf inet';
        $netstat_re = qr/^\S+(?:\s+\d+){2}\s+($ip_re)[:.](\d+)\s+($ip_
+re)[:.](\d+)\s+(\S+)\s*$/;
    }
    elsif( $^O eq 'linux' ) {
        $args = '-n --inet';
        $netstat_re = qr/^\S+(?:\s+\d+){2}\s+($ip_re)[:.](\d+)\s+($ip_
+re)[:.](\d+)\s+(\S+)\s*$/;
    }
    elsif( $^O eq 'solaris' ) {
        $args = '-nf inet';
        $netstat_re = qr/^($ip_re)\.(\d+)\s+($ip_re)\.(\d+)(?:\s+\d+){
+4}\s+(\S+)\s*$/;
    }
    elsif( $^O eq 'MSWin32' ) {
        $args = '-n';
        $netstat_re = qr/^\s+TCP\s+($ip_re):(\d+)\s+($ip_re):(\d+)\s+(
+\S+)\s*$/;
    }
    else {
        die "Don't know how to decode netstat on $^O\n" unless defined
+ $args;
    }
}

# resolve service names if we can
defined $_ and /\D/ and $_ = getservbyname($_,'tcp') || $_
    for ($watch_local_port, $watch_remote_port, $watch_port);

my %state;
my @col = qw(
    ESTABLISHED CLOSE_WAIT TIME_WAIT FIN_WAIT_1 FIN_WAIT_2 SYN_SENT SY
+N_RECV LAST_ACK
);
print "estab close twait finw1 finw2 syntx synrx lastk total\n";

while( 1 ) {
    my $total    = 0;
    @state{@col} = (0) x @col;

    open my $in, "netstat $args |"
        or die "Cannot open pipe from netstat: $!\n";
    while( <$in> ) {
        chomp;
        next unless my($local_host, $local_port, $remote_host, $remote
+_port, $state)
            = /$netstat_re/;
        next if $watch_port
            and $local_port  != $watch_port
            and $remote_port != $watch_port
        ;
        next if $watch_local_port  and $local_port  != $watch_local_po
+rt;
        next if $watch_remote_port and $remote_port != $watch_remote_p
+ort;

        $state =~ s/^(FIN_WAIT)(\d+)$/$1_$2/; # munge Linux variant
        ++$state{$state};
        ++$total;
    }
    close $in;

    # display one line of data
    my $timestamp = sprintf( '%02d:%02d:%02d', (localtime)[2,1,0] );
    printf "%5d %5d %5d %5d %5d %5d %5d %5d %5d %s",
        @state{@col}, $total, $timestamp;
    delete @state{@col};

    # deal with unknown or don't-care socket states
    if( %state ) {
        print ' ', join( ' ', map {"$_=$state{$_}"} sort keys %state )
+;
        %state = ();
    }
    print "\n";

    last if defined $num and --$num <= 0;
    sleep $sleep;
}

exit 0;

__END__

=head1 NAME

socksumm - Display a summary of open sockets

=head1 SYNOPSIS

B<socksumm> [B<-l>,B<-localport>] [B<-r>,B<-remoteport>] [B<-p>,B<-por
+t>] [B<-s>,B<-sleep>] [B<-n>,B<-num>] [B<-version>]

=head1 DESCRIPTION

Parse the output of the C<netstat(1)> command and produce a summary
of the socket connections on a port.

=head1 OPTIONS

=over 5

=item B<-l>,B<-localport>

Summarise socket connections on this local port. Numeric or symbolic n
+ames
(for example 389 or C<ldap>) are recognised. In otherwords, use this t
+o
monitor inbound connections.

=item B<-r>,B<-remoteport>

Summarise socket connections on this remote port. Numeric or symbolic 
+names
are recognised. Use this to monitor outbound connections.

=item B<-p>,B<-port>

Summarise socket connections on this port. Numeric or symbolic names
are recognised. Use this to monitor eitherbound connections.

=item B<-s>,B<-sleep>

Time to sleep between invocations of C<netstat>. A sixty (60) second s
+leep
time is assumed if this switch is omitted.

=item B<-n>,B<-number>

Produce this many summaries of C<netstat> and then exit.

=back

=head1 EXAMPLES

C<socksumm -l=ldap -s=10>

Summarise the inbound connections to the LDAP listener port. Will prod
+uce
output that looks similar to the following:

 estab close twait finw1 finw2 syntx synrx lastk total
   519     0     4     0     0     0     0     0   523 12:42:50
   524     0     2     0     0     0     0     1   527 12:43:00
   516     0     3     0     0     0     0     0   519 12:43:11

C<socksumm -r=22 -s=3600>

See how many outbound C<ssh> connections are open every hour.

=head1 BUGS

Assumes that C<netstat> can be found on the PATH. If you are running
C<netstat> on a platform other than FreeBSD, Linux or Solaris the
script will die. Please mail me the output and I'll endeavour to
incorporate it (or, better yet, send me patches).

=head1 COPYRIGHT

Copyright 2005-2006 David Landgren.

This script is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

=head1 AUTHOR

David Landgren
join chr(0x40) => reverse qw[landgren.net david]

=cut

Comment on socksumm -- Display a summary of open sockets
Download Code

Back to Code Catacombs

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: sourcecode [id://572712]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (8)
As of 2015-07-28 09:12 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (254 votes), past polls