Poor Man’s Network Traffic Meter

Set out tonight to find a way to log “network traffic” through the interfaces on my solaris box. What I was wanting was the actually amount of traffic going through the interfaces. First thought was to use netstat. But that only shows “packets” and the packets could be differing sizes. So I ended up using kstat. I wrote this simple little script to grab the interface names, and then use kstat to get the data out of the network module for each card:

#!/bin/ksh
#Get list of Ethernet Cards in machine:
MyHOST="`hostname`"
OS="`uname -r`"
if [ ${OS} == "5.10" ] ; then
   MyETHERS="`/usr/sbin/dladm show-dev | awk '{print $1}'`"
else
   MyETHERS="`/usr/sbin/ifconfig -a | awk '{print $1}' | grep \":\" | awk -F':' '{print $1}' | sort -u | grep -v \"^lo0\"`"
fi
COUNT=0
while [ $COUNT -lt 800 ]; 
  do
  for i in `echo $MyETHERS`
  do
    OBYTES="`/usr/bin/kstat -p -c net -n $i -s obytes64 | awk '{print $2}'`"
    RBYTES="`/usr/bin/kstat -p -c net -n $i -s rbytes64 | awk '{print $2}'`"
    SNAPTIME="`perl -e \"print(time());\"`"
    echo "${MyHOST},${i},${SNAPTIME},${OBYTES},${RBYTES}"
    OBYTES=
    RBYTES= 
    SNAPTIME=
  done
  sleep 10
  COUNT="`expr $COUNT + 1`"
done

You have to be root to run this, but that is only because of the dladm command I am using on Solaris 10. If you don’t want to run it as root, then comment out the if statement and just leave the line that uses ifconfig. When you run it, it will produce an output like this:

gonzo,elxl0,1252806095,37255837,715035
gonzo,rge0,1252806096,605012664015,863919572622
gonzo,elxl0,1252806106,37255837,715035
gonzo,rge0,1252806107,605012664377,863919573090

The output is formated as hostname, ethernet, time of the run, sending bytes, and receiving bytes. (The time is the epoch time.) The above script will only run 800 times, pausing 10 seconds between each run of the kstat. You can change how long it runs by changing the line:

while [ $COUNT -lt 800 ]; 

Just change the 800 to some other number. The second item to change is the “interval” time and that is controled by the :

sleep 10

You probably don’t want to run this every second. Every 10 is about right, as it will allow me to get the traffic with out much overhead.

The second script I did, was a little php script (but can be done in probably any language, but I use php for just about everything. This script takes output from the file you created above (just run the above script, redirect it to a file) and gives you a human readable output.

Note if you have more than one ethernet card active in your system, currently you will need to
“grep” out each card to it’s own file. If you have a bunch of machines, you should probably import the data from above in to a mysql db, and then modify this script to pull the info from it.

Here is the script to just parse one network card:

< ?php
date_default_timezone_set("EST");
$fp=fopen("Netstat.csv",r);
if ($fp) {
  $i=0;
  while (!feof($fp)) {
    $buffer=fgets($fp);
    if ($buffer) { 
      list($hostname&#91;$i&#93;,$ethernet&#91;$i&#93;,$time&#91;$i&#93;,$sending&#91;$i&#93;,$receiving&#91;$i&#93;) = explode(",",$buffer);
      $newtime=date('r',$time&#91;$i&#93;);
      if ($i != 0 ) {
        $TDIFF=($time&#91;$i&#93;-$time&#91;$i-1&#93;);
        $SDIFF=($sending&#91;$i&#93;-$sending&#91;$i-1&#93;)/$TDIFF/1024/1024;
        $RDIFF=($receiving&#91;$i&#93;-$receiving&#91;$i-1&#93;)/$TDIFF/1024/1024;
        printf("%s|%s|%s|%3.3f|%3.3f\n",$hostname&#91;$i&#93;,$ethernet&#91;$i&#93;,$newtime,$SDIFF,$RDIFF);
        $SDIFF="";
        $RDIFF="";
        $TDIFF="";
      }
      $i++;
    }
  }
}
fclose($fp);
?>

In the above, I named my redirected output to be Netstat.csv. What the above script outputs will look like this:

gonzo|rge0|Sat, 12 Sep 2009 15:44:38 -0500|0.000|0.000
gonzo|rge0|Sat, 12 Sep 2009 15:44:49 -0500|0.000|0.007
gonzo|rge0|Sat, 12 Sep 2009 15:45:04 -0500|6.677|0.065
gonzo|rge0|Sat, 12 Sep 2009 15:45:18 -0500|3.148|0.027
gonzo|rge0|Sat, 12 Sep 2009 15:45:41 -0500|5.377|0.076
gonzo|rge0|Sat, 12 Sep 2009 15:45:55 -0500|8.678|0.111
gonzo|rge0|Sat, 12 Sep 2009 15:46:16 -0500|9.499|0.117
gonzo|rge0|Sat, 12 Sep 2009 15:46:30 -0500|8.861|0.117
gonzo|rge0|Sat, 12 Sep 2009 15:46:46 -0500|9.183|0.120
gonzo|rge0|Sat, 12 Sep 2009 15:47:02 -0500|10.783|0.139
gonzo|rge0|Sat, 12 Sep 2009 15:47:15 -0500|7.103|0.093
gonzo|rge0|Sat, 12 Sep 2009 15:47:29 -0500|7.165|0.100
gonzo|rge0|Sat, 12 Sep 2009 15:47:44 -0500|6.995|0.095
gonzo|rge0|Sat, 12 Sep 2009 15:48:01 -0500|6.986|0.099
gonzo|rge0|Sat, 12 Sep 2009 15:48:15 -0500|5.678|0.069
gonzo|rge0|Sat, 12 Sep 2009 15:48:28 -0500|6.530|0.090
gonzo|rge0|Sat, 12 Sep 2009 15:48:53 -0500|3.477|0.046
gonzo|rge0|Sat, 12 Sep 2009 15:49:14 -0500|6.459|0.083
gonzo|rge0|Sat, 12 Sep 2009 15:49:31 -0500|7.754|0.105
gonzo|rge0|Sat, 12 Sep 2009 15:49:58 -0500|9.416|0.121
gonzo|rge0|Sat, 12 Sep 2009 15:50:10 -0500|10.854|0.139
gonzo|rge0|Sat, 12 Sep 2009 15:50:21 -0500|11.922|0.152
gonzo|rge0|Sat, 12 Sep 2009 15:50:31 -0500|12.556|0.165
gonzo|rge0|Sat, 12 Sep 2009 15:50:43 -0500|12.813|0.170
gonzo|rge0|Sat, 12 Sep 2009 15:50:54 -0500|14.783|0.188
gonzo|rge0|Sat, 12 Sep 2009 15:51:05 -0500|12.729|0.168
gonzo|rge0|Sat, 12 Sep 2009 15:51:16 -0500|12.018|0.148
gonzo|rge0|Sat, 12 Sep 2009 15:51:27 -0500|10.786|0.141
gonzo|rge0|Sat, 12 Sep 2009 15:51:38 -0500|13.566|0.167
gonzo|rge0|Sat, 12 Sep 2009 15:51:49 -0500|11.234|0.144
gonzo|rge0|Sat, 12 Sep 2009 15:52:01 -0500|12.914|0.165

The output is : hostname, ethernet, time of query,sending speed in Mbps, receiving speed in Mbps. As you can see from the above, I was copying some large amounts of data.

PHP 1, PERL & SED 0

So I have been trying to figure out how to get PERL and SED to replace a set of random characters in a line with a fixed set of characters. I tried for about 2 days on Perl and sed, but could not get it to work right. So last night I tried PHP and got it in one shot. So say I have a file that has a part of a line that looks like this:

Variable1=test&Variable2=test%2312&Variable3=92ns10i9js

and I want to replace what ever is in the Variable2 value to be just a bunch of X’s or some other fixed value. Nothing I could do in sed and Perl would work, I ended up with this in PHP:

$buffer2=ereg_replace(“&Variable2=(.*)&Variable3″,”&Variable2=XXXXXXXX&Variable3”,$buffer);

So can any one tell me how to do it in Perl or sed?