Perl Netstatスクリプト

12047 ワード

CUでこのシナリオを見て、いい感じです.具体的に細かいテストはありません.
後で自分で直してみて、前から似たようなことを書きたいと思っていましたが、時間がありませんでした.
#!/usr/bin/perl
# Written by FinalBSD at 2008-11-20.
# The netstat original written by C
# is expensive to me, so this born.
# As long as you retain this notice you
# can do whatever you want with this stuff. 
# If we meet some day, and you think
# this stuff is worth it, you can 
# buy me a beer in return.


use strict;
use warnings;
use Getopt::Std;

my $tcp         = "/proc/net/tcp";
my $tcp6         = "/proc/net/tcp6";
my $route        = "/proc/net/route";
my @tcpState         = ( 
                  "NULL",
                  "ESTABLISHED" ,
                  "SYN_SENT",
                  "SYN_RECV",
                  "FIN_WAIT1",
                  "FIN_WAIT2",
                  "TIME_WAIT",
                  "CLOSE",
                  "CLOSE_WAIT",
                  "LAST_ACK",
                  "LISTEN",
                  "CLOSING"     
);

my @routeType   = (
                   "NULL",
                  "U",                # UP
                  "G",                # Gateway
                  "UG"                # UP & Gateway
);

my %opts;
getopts('nhatsrl', \%opts);

if($opts{h}) {
        &usage();
}

if($opts{r}) {
        &route_info($route);
        exit;
}
&tcp_info($tcp);
&tcp_info($tcp6);


###################### FUNCTION DEFINITION ###########################
#############################
# Get statistics Information 
############################
sub tcp_info($) {
        my $file = shift;
        open(FH, $file) or die("$!");
        
        my $format = "%-30s  %-30s %-10s
"; printf($format," Local Address"," Foreign Address","State"); while(<FH>) { next if /local_address/; my @data = split; my $state = $tcpState[hex($data[3])]; # Show listening Sockets. if($opts{l}){ printf($format, &hextoint($data[1]), &hextoint($data[2]), $state) if $state =~ /LIST/; } else { printf($format, &hextoint($data[1]), &hextoint($data[2]), $state); } } close(FH); } ############################# # Convert hex to int ############################ sub hextoint($) { my $tmp = shift; my @data; my @ip; my $int; # if have ':', then it's addr:port,else just port. if( $tmp =~ /:/ ) { if( $tmp =~ /FFFF/ ) { @data = split /:/, $tmp; # break it and do convert later. @ip = $data[0] =~ /\w{2}/g; foreach my $index (12..15){ $ip[$index] = hex($ip[$index]); } $int = sprintf("%-5s %d.%d.%d.%d:%d", "tcp6",$ip[15], $ip[14], $ip[13], $ip[12], hex($data[1])); } else { @data = split /:/, $tmp; @ip = $data[0] =~ /\w{2}/g; foreach my $index (0..3){ $ip[$index] = hex($ip[$index]); } $int = sprintf("%-s %d.%d.%d.%d:%d", " ",$ip[3], $ip[2], $ip[1], $ip[0], hex($data[1])); } } else { @ip = $tmp =~ /\w{2}/g; foreach my $index (0..3){ $ip[$index] = hex($ip[$index]); } $int = sprintf("%d.%d.%d.%d", hex($ip[3]), hex($ip[2]), hex($ip[1]), hex($ip[0])); } return $int; } ############################# # Show Kernel route table ############################ sub route_info($) { my $routefile = shift; open(ROUTE, $routefile) or die ("Can't open route file!
"); my $header = "Iface Destination Gateway Flags Genmask
"; printf("%s", $header); my $format = "%-5s %-15s %-15s %-5s %-15s
"; while(<ROUTE>) { next if /Iface/; my @line = split; my ($iface, $dest, $gw, $flags, $mask ) = ($line[0], &hextoint($line[1]), &hextoint($line[2]), hex($line[3]), &hextoint($line[7])); printf($format, $iface, $dest, $gw, $routeType[$flags], $mask ); } close(ROUTE); } ############################# # Show help information ############################ sub usage { printf("%s

%-30s
%-30s
%-30s
%-30s
%-30s
%-30s
", "netstat written in Perl by FinalBSD.Copyright(c) 2008.", "-n Show numeric ip and port address.", "-r Display the kernel routing table.", "-a Show both listening and non-listening socktes.", "-t Show only TCP statistics.", "-l Show only listening sockets.", "-h Show help.", ); exit; }