返回列表 回复 发帖

一个查看服务器实时流量的perl脚本

  1. #!/usr/bin/perl

  2. BEGIN {
  3.         eval { require Time::HiRes; };
  4.         if ($@) {
  5.                 warn "You don't have Time::HiRes installed. Fallback to perl's built-in time functions";
  6.         } else {
  7.                 import Time::HiRes qw(time);
  8.         }
  9. };

  10. use strict;
  11. use POSIX qw(strftime);
  12. use Getopt::Std;

  13. my $PROC_NET_DEV = '/proc/net/dev';        # proc device to get the network statistics
  14. my $SLEEP_INTERVAL = 1;

  15. my $def_show_fields = ('bytes/k,packets,errs/M,out.colls');
  16. my $guess_field_length = 8;
  17. my %field_length_taken =
  18.         ( 'k' => 3, 'K' => 3,
  19.                 'm' => 6, 'M' => 6,
  20.                 'u' => 2,
  21.                 1 => 0
  22.         );
  23. my %field_data_taken =
  24.         ( 'k' => 1000, 'K' => 1024,
  25.                 'm' => 1000000, 'M' => 1048576,
  26.                 'u' => 512,
  27.                 1 => 1
  28.         );


  29. my %dev_ignore_show =
  30.         (
  31.         'list' => 'lo',
  32.         'type' => 0,        # 0 - ignore, 1 - show
  33.         );

  34. my $proc_net_dev_title_line;
  35. my %in_fields;
  36. my %out_fields;
  37. my $dev_show;

  38. my $start_time;
  39. my $end_time;
  40. my @total;

  41. my @show_fields = ();
  42. my @show_fields_unit = ();
  43. my @show_fields_length = ();

  44. my $max_run = 0;
  45. my $inffinity_run = 1;

  46. sub
  47. init()
  48. {
  49.         if (open (DEV, "<", $PROC_NET_DEV)) {
  50.                 $proc_net_dev_title_line = 0;
  51.                
  52.                 my $part1type = 'in';
  53.                 my $part2type = 'out';
  54.                 while (<DEV>) {
  55.                         last if (/^\s*[\w\d]+:/);
  56.                         ++$proc_net_dev_title_line;
  57.                        
  58.                         chomp;
  59.                         my ($devname, $part1, $part2) = split(/\s*\|\s*/);

  60.                         my @types1 = split(/\s+/, $part1);
  61.                         my @types2 = split(/\s+/, $part2);

  62.                         if (scalar(@types1) > 1) {
  63.                                 if ($part1type eq 'in') {
  64.                                         for (my $i = 0; $i < scalar(@types1); ++$i) {
  65.                                                 $in_fields{$types1[$i]} = $i;
  66.                                         }
  67.                                 } elsif ($part1type eq 'out') {
  68.                                         for (my $i = 0; $i < scalar(@types1); ++$i) {
  69.                                                 $out_fields{$types1[$i]} = $i;
  70.                                         }
  71.                                 } else {
  72.                                         die "unknown type $part1type";
  73.                                 }
  74.                                
  75.                                 if ($part2type eq 'in') {
  76.                                         for (my $i = 0; $i < scalar(@types2); ++$i) {
  77.                                                 $in_fields{$types2[$i]} = $i + scalar(@types1);
  78.                                         }
  79.                                 } elsif ($part2type eq 'out') {
  80.                                         for (my $i = 0; $i < scalar(@types2); ++$i) {
  81.                                                 $out_fields{$types2[$i]} = $i + scalar(@types1);
  82.                                         }
  83.                                 } else {
  84.                                         die "unknown type $part2type";
  85.                                 }
  86.                                
  87.                         } else {
  88.                                 if ($types1[0] =~ /^(receive|recv|in)$/i) {
  89.                                         $part1type = 'in'; $part2type = 'out';
  90.                                 } else {
  91.                                         $part1type = 'out'; $part2type = 'in';
  92.                                 }
  93.                         }
  94.                 }

  95.                 close (DEV);
  96.         } # endif (open (DEV, "<", "/proc/net/dev"))
  97.         else
  98.         {
  99.                 die "Unsupported /proc implementation. We can show you nothing.";
  100.         }
  101. }

  102. sub
  103. ntParseFields($)
  104. {
  105.         my $fieldDesc = shift;
  106.         my @in_f;
  107.         my @out_f;

  108.         foreach (split(/\s*,\s*/, $fieldDesc)) {
  109.                 if (lc(substr($_, 0, 3)) eq 'in.') {
  110.                         push @in_f, $_;
  111.                 } elsif (lc(substr($_, 0, 4)) eq 'out.') {
  112.                         push @out_f, $_;
  113.                 } else {
  114.                         push @in_f, 'in.' . $_;
  115.                         push @out_f, 'out.' . $_;
  116.                 }
  117.         }

  118.         @show_fields = (@in_f, @out_f);
  119.         foreach (@show_fields) {
  120.                 if (/\/(\w)$/) {
  121.                         if (lc($1) ne 'k' && lc($1) ne 'm' && lc($1) ne 'u') {
  122.                                 die "unknown unit \"$1\"";
  123.                         }
  124.                         push @show_fields_unit, $1;
  125.                         s/\/\w$//;
  126.                 } else {
  127.                         push @show_fields_unit, 1;
  128.                 }
  129.         }
  130. }

  131. sub
  132. valueInArray($\@;$)
  133. {
  134.         my $value = shift;
  135.         my $tmp = shift;
  136.         my @array = @{$tmp};
  137.         my $ignore_cases = shift;

  138.         if ($ignore_cases) {
  139.                 $value = lc($value);
  140.                 @array = map { lc } @array;
  141.         }
  142.        
  143.         foreach (@array) {
  144.                 return 1 if ($value eq $_);
  145.         }

  146.         return 0;
  147. }

  148. sub
  149. readProcDevNet()
  150. {
  151.         my %result = ();
  152.        
  153.         open (DEV, "<", $PROC_NET_DEV);
  154.         for (my $i = 0; $i < $proc_net_dev_title_line; ++$i) {
  155.                 <DEV>;
  156.         }

  157.         while (<DEV>) {
  158.                 my ($devname, $data) = split(/:/);

  159.                 $devname =~ s/^\s*//;
  160.                 $devname =~ s/\s*$//;

  161.                 my @devs = split(/\s*,\s*/, $dev_ignore_show{'list'});
  162.                 if ( $dev_ignore_show{'type'} ) {
  163.                         # show this devices only
  164.                         next unless (valueInArray($devname, @devs, 1));
  165.                 } else {
  166.                         # ignore this device
  167.                         next if (valueInArray($devname, @devs, 1));
  168.                 }

  169.                 chomp $data;
  170.                 $data =~ s/^\s*//;
  171.                 $data =~ s/\s*$//;
  172.                 my @datas = split(/\s+/, $data);

  173.                 my @tmp = ();
  174.                
  175.                 foreach (@show_fields) {
  176.                         my ($type, $name) = split(/\./);
  177.                         if ($type eq 'in') {
  178.                                 if (exists $in_fields{$name}) {
  179.                                         push @tmp, int($datas[$in_fields{$name}]);
  180.                                 } else {
  181.                                         warn "wrong field name in.$name";
  182.                                         push @tmp, 0;
  183.                                 }
  184.                         } elsif ($type eq 'out') {
  185.                                 if (exists $out_fields{$name}) {
  186.                                         push @tmp, int($datas[$out_fields{$name}]);
  187.                                 } else {
  188.                                         warn "wrong field name out.$name";
  189.                                         push @tmp, 0;
  190.                                 }
  191.                         } else {
  192.                                 warn "wrong type $type.$name";
  193.                                 push @tmp, 0;
  194.                         }
  195.                 }

  196.                 $result{$devname} = \@tmp;
  197.         }
  198.         close (DEV);

  199.         return \%result;
  200. }

  201. sub
  202. max($)
  203. {
  204.         return $_[0] > $_[1] ? $_[0] : $_[1];
  205. }

  206. sub
  207. ntSub(\@\@;$)
  208. {
  209.         my $array1 = shift;
  210.         my $array2 = shift;
  211.         my $maxuint = shift || 4294967295;

  212.         my @result = ();
  213.        
  214.         my $maxi = max(scalar(@$array1), scalar(@$array2));
  215.         for (my $i = 0; $i < $maxi; ++$i) {
  216.                 my $num1 = $array1->[$i] || 0;
  217.                 my $num2 = $array2->[$i] || 0;

  218.                 $num1 -= $num2;
  219.                 $num1 += $maxuint if ($num1 < 0);
  220.                 push @result, $num1;
  221.         }

  222.         return \@result;
  223. }

  224. sub
  225. ntCalcRate($\%\%)
  226. {
  227.         my $time1 = shift;
  228.         my $time2 = shift;
  229.         my $data1 = shift;
  230.         my $data2 = shift;

  231.         my $timeEpo = $time2 - $time1;
  232.         my $subResult;
  233.         my @result = ();
  234.         foreach my $dev (keys %$data1) {
  235.                 $subResult = ntSub(@{$data2->{$dev}}, @{$data1->{$dev}});
  236.                 for (my $i = 0 ; $i < scalar(@$subResult); ++$i) {
  237.                         $result[$i] += $subResult->[$i];
  238.                 }
  239.         }

  240.         $end_time = $time2;
  241.         for (my $i = 0; $i < scalar(@result); ++$i) {
  242.                 $total[$i] += $result[$i];
  243.                 $result[$i] /= $field_data_taken{$show_fields_unit[$i]} * $timeEpo;
  244.         }
  245.         wantarray() ? @result : \@result;
  246. }

  247. my $title;
  248. sub
  249. ntTitle()
  250. {
  251.         if (defined $title) {
  252.                 print $title;
  253.                 return;
  254.         }
  255.        
  256.         my @format1;
  257.         my @name1;
  258.         my @format2;
  259.         my @name2;
  260.         my $nflag;
  261.         my $last_2nd;
  262.         my $dev = '(' . $dev_show . ')';
  263.        
  264.         push @format1, '@' . '|' x max(length($dev) - 1, 7);        # time
  265.         push @name1, $dev;
  266.         push @format2, '@' . '>' x (length($format1[0]) - 1);
  267.         push @name2, 'time';
  268.         $last_2nd = 1;
  269.        
  270.         for (my $i = 0; $i < scalar(@show_fields); ++$i) {
  271.                 my ($type, $name) = split(/\./, $show_fields[$i]);
  272.                 $name = $show_fields_unit[$i] . $name if ($show_fields_unit[$i] != 1);
  273.                 push @name2, $name;
  274.                 $show_fields_length[$i] = max($guess_field_length - $field_length_taken{$show_fields_unit[$i]}, length($name) + 1);
  275.                 push @format2, '@' . '>' x ($show_fields_length[$i] - 1);

  276.                 if (!defined $nflag) {
  277.                         if (lc($type) eq 'in') {
  278.                                 $nflag = 1;
  279.                         } elsif (lc($type) eq 'out') {
  280.                                 $nflag = 2;
  281.                         } else {
  282.                                 die "...";
  283.                         }
  284.                 } elsif ($nflag == 1) {
  285.                         if (lc($type) eq 'in') {
  286.                         } elsif (lc($type) eq 'out') {
  287.                                 $nflag = 2;
  288.                                 push @name1, 'input';
  289.                                 push @format1, '@' . '|' x (length( join(' ', @format2[$last_2nd .. $#format2-1]) ) - 1);
  290.                                 $last_2nd = $#format2;
  291.                         } else {
  292.                                 die '...';
  293.                         }
  294.                 } elsif ($nflag == 2) {
  295.                         if (lc($type) eq 'in') {
  296.                                 $nflag = 1;
  297.                                 push @name1, 'output';
  298.                                 push @format1, '@' . '|' x (length( join(' ', @format2[$last_2nd .. $#format2-1]) ) - 1);
  299.                                 $last_2nd = $#format2;
  300.                         } elsif (lc($type) eq 'out') {
  301.                         } else {
  302.                                 die '...';
  303.                         }
  304.                 } else {
  305.                         die "...?";
  306.                 }
  307.         }
  308.        
  309.         if ($nflag == 1) {
  310.                 push @name1, 'input';
  311.                 push @format1, '@' . '|' x (length( join(' ', @format2[$last_2nd .. $#format2]) ) - 1);
  312.         } elsif ($nflag == 2) {
  313.                 push @name1, 'output';
  314.                 push @format1, '@' . '|' x (length( join(' ', @format2[$last_2nd .. $#format2]) ) - 1);
  315.         } else {
  316.                 die "...";
  317.         }

  318.         formline join('*', @format1) . "\n", @name1;
  319.         formline join(' ', @format2) . "\n", @name2;
  320.         $title = $^A;
  321.         $^A = '';
  322.        
  323.         print $title;
  324.         return;
  325. }

  326. my $lineformat;
  327. sub
  328. ntLine($@)
  329. {
  330.         my $the_time = strftime("%H:%M:%S", localtime(shift));
  331.         if (!defined $lineformat) {
  332.                
  333.                 my @format = ();
  334.                 my $dev = '(' . $dev_show . ')';
  335.        
  336.                 push @format, '@' . '>' x max(length($dev) - 1, 7);
  337.                 for (my $i = 0; $i < scalar(@show_fields_length); ++$i) {
  338.                         push @format, '@' . '#' x ($show_fields_length[$i] - 1);
  339.                 }

  340.                 $lineformat = join(' ', @format);
  341.         }
  342.        
  343.         formline $lineformat, $the_time, @_;
  344.         print $^A, "\n";
  345.         $^A = '';
  346. }

  347. sub
  348. ntStatics()
  349. {
  350.         my $timeEpo = $end_time - $start_time;
  351.        
  352.         printf("\n\nStatics: begin at %s\tend at %s\n",
  353.                 strftime("%H:%M:%S", localtime($start_time)),
  354.                 strftime("%H:%M:%S", localtime($end_time)) );
  355.         ntTitle();
  356.        
  357.         for (my $i = 0; $i < scalar(@total); ++$i) {
  358.                 $total[$i] /= $timeEpo * $field_data_taken{$show_fields_unit[$i]};
  359.         }
  360.         ntLine($end_time, @total);
  361.         exit(0);
  362. }

  363. sub
  364. ntParseArgument(\%)
  365. {
  366.         my $arg = shift;

  367.         foreach my $keyname (keys %{$arg}) {
  368.                 if ($keyname eq 'i') {
  369.                         # interface to show
  370.                         $dev_ignore_show{'list'} = $arg->{'i'};
  371.                         $dev_ignore_show{'type'} = 1;
  372.                 } elsif ($keyname eq 'I') {
  373.                         # interface to ignore
  374.                         $dev_ignore_show{'list'} = $arg->{'I'};
  375.                         $dev_ignore_show{'type'} = 0;
  376.                 } elsif ($keyname eq 'c') {
  377.             $max_run = $arg->{'c'};
  378.             $inffinity_run = 0;
  379.         }
  380.         }

  381.         return;
  382. }

  383. sub
  384. ntShowHelp($)
  385. {
  386.         print <<"EOF";
  387.     nettraf - Show the network traffic in a linux box.
  388.         nettraf will get the statistics from the proc file system ( NORMALLY, /proc/net/dev)

  389.         i                        Interface list to show.
  390.         I                        Ignore interface list.
  391.         c           Max show lines.
  392. EOF
  393.         exit($_[0]);
  394. }

  395. ###########################
  396. # main
  397. ###########################
  398. {
  399.         my %arguments;
  400.         unless (getopts('i:I:c:', \%arguments)) {
  401.                 ntShowHelp(-1);
  402.         }

  403.         ntParseArgument(%arguments);
  404.         init();
  405.         $SIG{INT} = \&ntStatics;
  406.         ntParseFields($def_show_fields);
  407.         my $this_time = time;
  408.         my $this_data = readProcDevNet();
  409.         $start_time = $this_time;

  410.         my $line_show_count = 0;       
  411.         $dev_show = join('+', keys %$this_data);
  412.         while ($inffinity_run || $line_show_count < $max_run) {
  413.                 ntTitle() if (($line_show_count++ % 25) == 0);

  414.                 sleep($SLEEP_INTERVAL);
  415.                 my $last_data = $this_data;
  416.                 my $last_time = $this_time;
  417.                 $this_time = time;
  418.                 $this_data = readProcDevNet();

  419.                 my $calcResult = ntCalcRate($last_time, $this_time, %$last_data, %$this_data);
  420.                 ntLine($this_time, @$calcResult);
  421.         }
  422.     ntStatics();
  423. }
复制代码
返回列表
开源邮件服务器 开源邮件服务器 web 开源邮件 开源 mail 开源 邮件服务器 邮件技术 mail技术 反垃圾邮件 反垃圾mail mail投递
邮件服务器 mail服务器 开源软件 mail软件 mail服务新品牌 开源邮件服务新品牌
开源mail服务新网站 邮件服务新品牌 mail tmail mailserver 163邮件 sendmail |Linux维护|Linux代维|成都Linux维护|成都Linux代维