免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 9004 | 回复: 12

Perl写的简化版netstat,欢迎批评 [复制链接]

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
发表于 2008-11-20 13:26 |显示全部楼层
写作意图:
Linux系统自带的netstat在很多时候抓信息会发现耗CPU很高,特别是在做一些监控系统的时候,
发现如果使用了netstat,监控系统本身会造成系统负载比较高,因此试着用perl写下,time测试比自带的
netstat更快更节省资源,欢迎批评,呵呵。

  1. #!/usr/bin/perl
  2. # Written by FinalBSD at 2008-11-20.
  3. # The netstat original written by C
  4. # is expensive to me, so this born.
  5. # As long as you retain this notice you
  6. # can do whatever you want with this stuff.
  7. # If we meet some day, and you think
  8. # this stuff is worth it, you can
  9. # buy me a beer in return.


  10. use strict;
  11. use warnings;
  12. use Getopt::Std;

  13. my $tcp         = "/proc/net/tcp";
  14. my $tcp6         = "/proc/net/tcp6";
  15. my $route        = "/proc/net/route";
  16. my @tcpState         = (
  17.                   "NULL",
  18.                   "ESTABLISHED" ,
  19.                   "SYN_SENT",
  20.                   "SYN_RECV",
  21.                   "FIN_WAIT1",
  22.                   "FIN_WAIT2",
  23.                   "TIME_WAIT",
  24.                   "CLOSE",
  25.                   "CLOSE_WAIT",
  26.                   "LAST_ACK",
  27.                   "LISTEN",
  28.                   "CLOSING"     
  29. );

  30. my @routeType   = (
  31.                   "NULL",
  32.                   "U",                # UP
  33.                   "G",                # Gateway
  34.                   "UG"                # UP & Gateway
  35. );

  36. my %opts;
  37. getopts('nhatsrl', \%opts);

  38. if($opts{h}) {
  39.         &usage();
  40. }

  41. if($opts{r}) {
  42.         &route_info($route);
  43.         exit;
  44. }
  45. &tcp_info($tcp);
  46. &tcp_info($tcp6);


  47. ###################### FUNCTION DEFINITION ###########################
  48. #############################
  49. # Get statistics Information
  50. ############################
  51. sub tcp_info($) {
  52.         my $file = shift;
  53.         open(FH, $file) or die("$!");
  54.        
  55.         my $format = "%-30s  %-30s %-10s\n";               
  56.         printf($format,"      Local Address","      Foreign Address","State");
  57.         while(<FH>) {
  58.                 next if /local_address/;
  59.                 my @data = split;
  60.                
  61.                 my $state = $tcpState[hex($data[3])];       
  62.                 # Show listening Sockets.
  63.                 if($opts{l}){
  64.                         printf($format, &hextoint($data[1]), &hextoint($data[2]), $state) if $state =~ /LIST/;
  65.                 } else {
  66.                         printf($format, &hextoint($data[1]), &hextoint($data[2]), $state);
  67.                 }
  68.         }
  69.         close(FH);
  70. }

  71. #############################
  72. # Convert hex to int
  73. ############################
  74. sub hextoint($) {
  75.         my $tmp         = shift;
  76.         my @data;
  77.         my @ip;
  78.         my $int;

  79.         # if have ':', then it's  addr:port,else just port.
  80.         if( $tmp =~ /:/ ) {
  81.                 if( $tmp =~ /FFFF/ ) {
  82.                         @data = split /:/, $tmp;
  83.                         # break it and do convert later.
  84.                         @ip   = $data[0] =~ /\w{2}/g;
  85.                                
  86.                         foreach my $index (12..15){
  87.                                 $ip[$index] = hex($ip[$index]);
  88.                         }
  89.                                
  90.                         $int  = sprintf("%-5s %d.%d.%d.%d:%d", "tcp6",$ip[15], $ip[14], $ip[13], $ip[12], hex($data[1]));
  91.                 } else {
  92.                         @data = split /:/, $tmp;
  93.                         @ip   = $data[0] =~ /\w{2}/g;
  94.                         foreach my $index (0..3){
  95.                                 $ip[$index] = hex($ip[$index]);
  96.                         }
  97.                         $int  = sprintf("%-s %d.%d.%d.%d:%d", "     ",$ip[3], $ip[2], $ip[1], $ip[0], hex($data[1]));
  98.                 }
  99.         } else {
  100.                 @ip   = $tmp =~ /\w{2}/g;
  101.                 foreach my $index (0..3){
  102.                         $ip[$index] = hex($ip[$index]);
  103.                 }
  104.                 $int  = sprintf("%d.%d.%d.%d", hex($ip[3]), hex($ip[2]), hex($ip[1]), hex($ip[0]));
  105.         }

  106.         return $int;
  107. }

  108. #############################
  109. # Show Kernel route table
  110. ############################
  111. sub route_info($) {
  112.         my $routefile = shift;
  113.         open(ROUTE, $routefile) or die ("Can't open route file!\n");
  114.         my $header = "Iface  Destination     Gateway      Flags   Genmask\n";
  115.         printf("%s", $header);
  116.         my $format = "%-5s %-15s %-15s %-5s %-15s\n";
  117.         while(<ROUTE>) {
  118.                 next if /Iface/;
  119.                 my @line = split;
  120.                 my ($iface, $dest, $gw, $flags, $mask ) = ($line[0], &hextoint($line[1]), &hextoint($line[2]), hex($line[3]), &hextoint($line[7]));
  121.                 printf($format, $iface, $dest, $gw, $routeType[$flags], $mask );
  122.         }
  123.         close(ROUTE);
  124. }

  125. #############################
  126. # Show help information
  127. ############################
  128. sub usage {
  129.         printf("%s\n\n%-30s\n%-30s\n%-30s\n%-30s\n%-30s\n%-30s\n",
  130.                      "netstat written in Perl by FinalBSD.Copyright(c) 2008.",
  131.                      "-n Show numeric ip and port address.",
  132.                      "-r Display the kernel routing table.",
  133.                      "-a Show both listening and non-listening socktes.",
  134.                      "-t Show only TCP statistics.",
  135.                      "-l Show only listening sockets.",
  136.                      "-h Show help.",
  137.         );
  138.         exit;               
  139. }

复制代码

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
发表于 2008-11-20 14:00 |显示全部楼层
其实我觉得封装成 Module 要比封装成命令行工具更有价值。

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
发表于 2008-11-20 16:30 |显示全部楼层
原帖由 flw 于 2008-11-20 14:00 发表
其实我觉得封装成 Module 要比封装成命令行工具更有价值。

呵呵,想法很好,之前没写过Module,简单写了下,flw老大看下是不是这样写:


  1. package netstat;
  2. our $VERSION=0.01;

  3. use strict;
  4. require Exporter;
  5. our @ISA= qw(Exporter);
  6. our @EXPORT_OK = qw(all_info tcp_info tcp6_info route_info tcp_listen);
  7. use warnings;
  8. $| = 1;

  9. my $tcp = "/proc/net/tcp";
  10. my $tcp6 = "/proc/net/tcp6";

  11. my @tcpState         = (
  12.                   "NULL",
  13.                   "ESTABLISHED" ,
  14.                   "SYN_SENT",
  15.                   "SYN_RECV",
  16.                   "FIN_WAIT1",
  17.                   "FIN_WAIT2",
  18.                   "TIME_WAIT",
  19.                   "CLOSE",
  20.                   "CLOSE_WAIT",
  21.                   "LAST_ACK",
  22.                   "LISTEN",
  23.                   "CLOSING"     
  24. );

  25. my @routeType   = (
  26.                   "NULL",
  27.                   "U",                # UP
  28.                   "G",                # Gateway
  29.                   "UG"                # UP & Gateway
  30. );


  31. ###################### FUNCTION DEFINITION ###########################
  32. #############################
  33. # Get statistics Information
  34. ############################
  35. sub tcp_info() {
  36.         my $file = shift || $tcp;
  37.         my $mode = shift;
  38.         open(FH, $file) or die("$!");
  39.         my @result;
  40.         my $tmp;
  41.        
  42.         my $format = "%-30s  %-30s %-10s\n";               
  43.         my $header = sprintf($format,"      Local Address","      Foreign Address","State");
  44.         push(@result, $header);
  45.         while(<FH>) {
  46.                 next if /local_address/;
  47.                 my @data = split;
  48.                
  49.                 my $state = $tcpState[hex($data[3])];       
  50.                 # Show listening Sockets.
  51.                 if($mode){
  52.                         if($state =~ /LIST/ ) {
  53.                                 $tmp = sprintf($format, &hextoint($data[1]), &hextoint($data[2]), $state);
  54.                                 push(@result, $tmp);
  55.                         }
  56.                 } else {
  57.                         $tmp = sprintf($format, &hextoint($data[1]), &hextoint($data[2]), $state);
  58.                         push(@result, $tmp);
  59.                 }
  60.         }
  61.         close(FH);
  62.         return(@result);
  63. }
  64. sub tcp6_info {
  65.         my $file = $tcp6;
  66.         &tcp_info($file);

  67. }

  68. sub tcp_listen {
  69.         my $mode = 1;
  70.         my (@r1,@r2);
  71.         @r1 = &tcp_info($tcp,$mode);
  72.         @r2 = &tcp_info($tcp6,$mode);
  73.         return(@r1,@r2);
  74.        
  75. }

  76. sub all_info {
  77.         my (@r1,@r2);
  78.         @r1 =  &tcp_info();
  79.         @r2 =  &tcp6_info();
  80.         return(@r1,@r2);

  81. }
  82. #############################
  83. # Convert hex to int
  84. ############################
  85. sub hextoint($) {
  86.         my $tmp         = shift;
  87.         my @data;
  88.         my @ip;
  89.         my $int;

  90.         # if have ':', then it's  addr:port,else just port.
  91.         if( $tmp =~ /:/ ) {
  92.                 if( $tmp =~ /FFFF/ ) {
  93.                         @data = split /:/, $tmp;
  94.                         # break it and do convert later.
  95.                         @ip   = $data[0] =~ /\w{2}/g;
  96.                                
  97.                         foreach my $index (12..15){
  98.                                 $ip[$index] = hex($ip[$index]);
  99.                         }
  100.                                
  101.                         $int  = sprintf("%-5s %d.%d.%d.%d:%d", "tcp6",$ip[15], $ip[14], $ip[13], $ip[12], hex($data[1]));
  102.                 } else {
  103.                         @data = split /:/, $tmp;
  104.                         @ip   = $data[0] =~ /\w{2}/g;
  105.                         foreach my $index (0..3){
  106.                                 $ip[$index] = hex($ip[$index]);
  107.                         }
  108.                         $int  = sprintf("%-s %d.%d.%d.%d:%d", "     ",$ip[3], $ip[2], $ip[1], $ip[0], hex($data[1]));
  109.                 }
  110.         } else {
  111.                 @ip   = $tmp =~ /\w{2}/g;
  112.                 foreach my $index (0..3){
  113.                         $ip[$index] = hex($ip[$index]);
  114.                 }
  115.                 $int  = sprintf("%d.%d.%d.%d", hex($ip[3]), hex($ip[2]), hex($ip[1]), hex($ip[0]));
  116.         }

  117.         return $int;
  118. }

  119. #############################
  120. # Show Kernel route table
  121. ############################
  122. sub route_info() {
  123.         my $routefile = shift || "/proc/net/route";
  124.         open(ROUTE, $routefile) or die ("Can't open route file!\n");
  125.         my $header = "Iface  Destination     Gateway      Flags   Genmask\n";
  126.         printf("%s", $header);
  127.         my $format = "%-5s %-15s %-15s %-5s %-15s\n";
  128.         while(<ROUTE>) {
  129.                 next if /Iface/;
  130.                 my @line = split;
  131.                 my ($iface, $dest, $gw, $flags, $mask ) = ($line[0], &hextoint($line[1]), &hextoint($line[2]), hex($line[3]), &hextoint($line[7]));
  132.                 printf($format, $iface, $dest, $gw, $routeType[$flags], $mask );
  133.         }
  134.         close(ROUTE);
  135. }

  136. 1;
  137. __END__

  138. =head1 NAME

  139.   netstat - Perl module of netstat.

  140. =head1 DESCRIPTION

  141.   Netstat module provides to you a simple way for getting the current tcp open ports
  142.   (connections, routing tables) on a local system (Linux).

  143. =head1 SYNOPSIS

  144.   use netstat;
  145.   use netstat qw(tcp_info tcp6_info all_info tcp_listen);

  146.   print "Tcp Connection Statistics:\n\n";
  147.   @netstat = netstat::all_info;
  148.   for (@netstat) { print "$_\n"; }

  149.   print "Tcp(ipv4) Connection Statistics:\n\n";
  150.   @netstat = netstat::tcp_info;
  151.   for (@netstat) { print "$_\n"; }

  152.   print "Tcp(ipv6) Connection Statistics:\n\n";
  153.   @netstat = netstat::tcp6_info;
  154.   for (@netstat) { print "$_\n"; }

  155.   print "Tcp(LISTENING) Statistics:\n\n";
  156.   @netstat = netstat::tcp_listen;
  157.   for (@netstat) { print "$_\n"; }

  158.   

  159. =head1 METHODS

  160. =head2 all_info()

  161.   @netstat = netstat::all_info();

  162.   Get the All tcp connections.

  163. =head2 tcp_info()

  164.   @netstat = netstat::tcp_info();

  165.   Get the All tcp(ipv4) connections.

  166. =head2 tcp6_info()

  167.   @netstat = netstat::tcp6_info();

  168.   Get the All tcp(ipv6) connections.

  169. =head2 tcp_listen()

  170.   @netstat = netstat::tcp_listen();

  171.   Get the All tcp(listening) connections.

  172. =head1 SYSTEM REQUIREMENTS

  173.   This module requires Linux Platform to run.  

  174. =head1 SEE ALSO

  175.   man netstat

  176. =head1 AUTHOR

  177.   FinalBSD [email]finalbsd@finalbsd.org[/email]
  178.   [url]http://www.sanotes.net[/url]

  179. =head1 COPYRIGHT

  180.   Copyright (c) 2008 FinalBSD. All rights reserved.
  181.   This program is free software; you can redistribute it
  182.   and/or modify it under the same terms as Perl itself.

  183. =cut

复制代码

netstat.pm

4.76 KB, 下载次数: 189

论坛徽章:
0
发表于 2008-11-20 16:46 |显示全部楼层
还提供代码下载,真人性化啊,还没仔细看,先顶你一下。

论坛徽章:
0
发表于 2008-11-27 18:38 |显示全部楼层
好人哪

论坛徽章:
0
发表于 2008-11-28 09:31 |显示全部楼层
谢谢楼主分享!

论坛徽章:
0
发表于 2008-12-02 12:07 |显示全部楼层
后面说的module方式怎么用?

不知道怎么用,只好复制前面的代码做脚本来用了。

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
发表于 2008-12-02 12:16 |显示全部楼层
原帖由 defage 于 2008-12-2 12:07 发表
后面说的module方式怎么用?

不知道怎么用,只好复制前面的代码做脚本来用了。

perldoc netstat.pm

论坛徽章:
0
发表于 2008-12-03 15:36 |显示全部楼层
学习的好例子,我来慢慢看看

论坛徽章:
1
辰龙
日期:2014-05-15 19:37:15
发表于 2008-12-10 10:29 |显示全部楼层
my $file = shift;

我认真读了一下,一直不明白楼主这句是什么意思,要做些什么.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP