Академический Документы
Профессиональный Документы
Культура Документы
/usr/bin/perl -w
#
# nicstat - print network traffic, Kbyte/s read and written.
#
Solaris 8+, Perl (Sun::Solaris::Kstat).
#
# "netstat -i" only gives a packet count, this program gives Kbytes.
#
# 30-Sep-2006, ver 1.00 (check for new versions, http://www.brendangregg.com)
#
# USAGE:
nicstat [-hsz] [-i int[,int...]] | [interval [count]]
#
#
-h
# help
#
-s
# print summary output
#
-z
# skip zero lines
#
-i int[,int...] # print these instances only
# eg,
#
nicstat
# print summary since boot
#
nicstat 1
# print continually, every 1 second
#
nicstat 1 5
# print 5 times, every 1 second
#
nicstat -i hme0 # only examine hme0
#
# This prints out the KB/s transferred for all the network cards (NICs),
# including packet counts and average sizes. The first line is the summary
# data since boot.
#
# FIELDS:
#
Int
Interface
#
rKB/s
read Kbytes/s
#
wKB/s
write Kbytes/s
#
rPk/s
read Packets/s
#
wPk/s
write Packets/s
#
rAvs
read Average size, bytes
#
wAvs
write Average size, bytes
#
%Util
%Utilisation (r+w/ifspeed)
#
Sat
Saturation (defer, nocanput, norecvbuf, noxmtbuf)
#
# NOTES:
#
# - Some unusual network cards may not provide all the details to Kstat,
# (or provide different symbols). Check for newer versions of this program,
# and the @Network array in the code below.
# - Utilisation is based on bytes transferred divided by speed of the interface
# (if the speed is known). It should be impossible to reach 100% as there
# are overheads due to bus negotiation and timing.
# - Loopback interfaces may only provide packet counts (if anything), and so
# bytes and %util will always be zero. Newer versions of Solaris (newer than
# Solaris 10 6/06) may provide loopback byte stats.
# - Saturation is determined by counting read and write errors caused by the
# interface running at saturation. This approach is not ideal, and the value
# reported is often lower than it should be (eg, 0.0). Reading the rKB/s and
# wKB/s fields may be more useful.
#
# SEE ALSO:
#
nicstat.c
# the C version, also on my website
#
kstat -n hme0 [interval [count]]
# or qfe0, ...
#
netstat -iI hme0 [interval [count]]
#
se netstat.se [interval]
# SE Toolkit
#
se nx.se [interval]
# SE Toolkit
#
# COPYRIGHT: Copyright (c) 2006 Brendan Gregg.
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
This program is
modify it under
as published by
of the License,
Brendan Gregg
"
"
"
"
"
"
"
"
"
"
Created this.
added saturation value.
added summary style (from Peter Tribble).
Tweaked style.
Improved output neatness.
Added loopback, tweaked output.
use strict;
use Getopt::Std;
use Sun::Solaris::Kstat;
my $Kstat = Sun::Solaris::Kstat->new();
#
# Process command line args
#
usage() if defined $ARGV[0] and $ARGV[0] eq "--help";
getopts('hi:sz') or usage();
usage() if defined $main::opt_h;
my $STYLE = defined $main::opt_s ? $main::opt_s : 0;
my $SKIPZERO = defined $main::opt_z ? $main::opt_z : 0;
# process [interval [count]],
my ($interval, $loop_max);
if (defined $ARGV[0]) {
$interval = $ARGV[0];
$loop_max = defined $ARGV[1] ? $ARGV[1] : 2**32;
usage() if $interval == 0;
}
else {
$interval = 1;
$loop_max = 1;
}
# check for -i,
my %NetworkOnly;
# network interfaces to print
my $NETWORKONLY = 0;
# match on network interfaces
if (defined $main::opt_i) {
foreach my $net (split /,/, $main::opt_i) {
$NetworkOnly{$net} = 1;
}
$NETWORKONLY = 1;
}
# globals,
my $loop = 0;
my $PAGESIZE = 20;
my $line = $PAGESIZE;
my %NetworkNames;
my %NetworkData;
my %NetworkDataOld;
$main::opt_h = 0;
$| = 1;
#
#
#
#
#
#
# autoflush
else {
$old_rbytes = $old_wbytes = $old_rpackets = $old_wpackets
= $old_sat = $old_time = 0;
}
#
# Calculate statistics
#
# delta time
my $tdiff = $time - $old_time;
# per second values
my $rbps = ($rbytes - $old_rbytes) / $tdiff;
my $wbps = ($wbytes - $old_wbytes) / $tdiff;
my $rkps = $rbps / 1024;
my $wkps = $wbps / 1024;
my $rpps = ($rpackets - $old_rpackets) / $tdiff;
my $wpps = ($wpackets - $old_wpackets) / $tdiff;
my $ravs = $rpps > 0 ? $rbps / $rpps : 0;
my $wavs = $wpps > 0 ? $wbps / $wpps : 0;
# skip zero lines if asked
next if $SKIPZERO and ($rbps + $wbps) == 0;
# % utilisation
my $util;
if ($speed > 0) {
# the following has a mysterious "800", it is 100
# for the % conversion, and 8 for bytes2bits.
$util = ($rbps + $wbps) * 800 / $speed;
$util = 100 if $util > 100;
}
else {
$util = 0;
}
# saturation per sec
my $sats = ($sat - $old_sat) / $tdiff;
#
# Print statistics
#
if ($rbps ne "") {
my @Time = localtime();
if ($STYLE == 0) {
printf "%02d:%02d:%02d %7s ",
$Time[2], $Time[1], $Time[0], $int;
print_neat($rkps);
print_neat($wkps);
print_neat($rpps);
print_neat($wpps);
print_neat($ravs);
print_neat($wavs);
printf "%7.2f %6.2f\n", $util, $sats;
}
elsif ($STYLE == 1) {
printf "%02d:%02d:%02d %8s %14.3f %14.3f\n",
$Time[2], $Time[1], $Time[0], $int, $rkps, $wkps;
}
$line++;
# for multiple interfaces, always print the header
$line += $PAGESIZE if @NetworkData > 1;
}
### Store old values
$NetworkDataOld{$int}
= "$rbytes:$wbytes:$rpackets:$wpackets:$sat:$time";
}
### Check for end
last if ++$loop == $loop_max;
### Interval
sleep $interval;
}
# find_nets - walk Kstat to discover network interfaces.
#
# This walks %Kstat and populates a %NetworkNames with discovered
# network interfaces.
#
sub find_nets {
my $found = 0;
### Loop over all Kstat modules
foreach my $module (keys %$Kstat) {
my $Modules = $Kstat->{$module};
foreach my $instance (keys %$Modules) {
my $Instances = $Modules->{$instance};
foreach my $name (keys %$Instances) {
### Skip interface if asked
if ($NETWORKONLY) {
next unless $NetworkOnly{$name};
}
### Skip if not the regular statistic set
next unless $name =~ /^$module/;
my $Names = $Instances->{$name};
# Check this is a network device.
# Matching on ifspeed has been more reliable than "class"
# we also match loopback interfaces.
if (defined $$Names{ifspeed} || $module eq "lo") {
### Save network interface
$NetworkNames{$name} = $Names;
$found++;
}
}
}
}
return $found;
}
# fetch - fetch Kstat data for the network interfaces.
#
# This uses the interfaces in %NetworkNames and returns useful Kstat data.
# The Kstat values used are rbytes64, obytes64, ipackets64, opackets64
# (or the 32 bit versions if the 64 bit values are not there).
#
sub fetch_net_data {
my ($rbytes, $wbytes, $rpackets, $wpackets, $speed, $time);
my @NetworkData = ();
$Kstat->update();
### Loop over previously found network interfaces
foreach my $name (keys %NetworkNames) {
my $Names = $NetworkNames{$name};
if (defined $$Names{opackets}) {
### Fetch write bytes
if (defined $$Names{obytes64}) {
$rbytes = $$Names{rbytes64};
$wbytes = $$Names{obytes64};
}
elsif (defined $$Names{obytes}) {
$rbytes = $$Names{rbytes};
$wbytes = $$Names{obytes};
} else {
$rbytes = $wbytes = 0;
}
### Fetch read bytes
if (defined $$Names{opackets64}) {
$rpackets = $$Names{ipackets64};
$wpackets = $$Names{opackets64};
}
else {
$rpackets = $$Names{ipackets};
$wpackets = $$Names{opackets};
}
### Fetch interface speed
if (defined $$Names{ifspeed}) {
$speed = $$Names{ifspeed};
}
else {
# if we can't fetch the speed, print the
# %Util as 0.0 . To do this we,
$speed = 2 ** 48;
}
### Determine saturation value
my $sat = 0;
if (defined $$Names{nocanput} or defined $$Names{norcvbuf}) {
$sat += defined $$Names{defer} ? $$Names{defer} : 0;
$sat += defined $$Names{nocanput} ? $$Names{nocanput} : 0;
$sat += defined $$Names{norcvbuf} ? $$Names{norcvbuf} : 0;