Date created: 03/05/12 17:40:22. Last modified: 03/28/16 13:57:49

Linux Host Interface Throughput

expect-server.sh - This script will SSH to a host and run 'ifconfig' every second, looking at the number of bytes sent and received. The difference in these values second by second is the rough speed the interface is transmitting/receiving at.

This is a variation on this script for Cisco devices.

The below example is an iPerf test at 1Mbps between two servers, over UDP;

#!/usr/bin/expect 

# Expect script to grab ifconfig interface throughput, second by second
# by jwbensley<at>gmail.com
# If you don't like it, fuck off.

# Long delay for those tricky hostnames

set timeout 60

# Prompt user for server host name/IP address, username, password, 
# path to `ifconfig`, interface to query (example: eth0), and query
# interval in seconds (default, 1)

send_user "Hostname: "
expect_user -re "(.*)\n"
set host $expect_out(1,string)

send_user "Username: "
expect_user -re "(.*)\n"
set user $expect_out(1,string)

# Don't show the password it is typed
stty -echo
send_user "Password: "
expect_user -re "(.*)\n"
set pass $expect_out(1,string)
send_user "\n"
stty echo

send_user "SSH port \[22\]: "
expect_user -re "(.*)\n"
set sshport $expect_out(1,string)
# Use 22 as the default SSH port if none is given
if { $sshport == "" } {
  set sshport 22
}

send_user "Path to 'ifconfig' \[\/sbin\/ifconfig\]: "
expect_user -re "(.*)\n"
set ifpath $expect_out(1,string)
# Use /sbin/ifconfig as the default path to ifconfig if none is given
if { $ifpath == "" } {
  set ifpath "/sbin/ifconfig"
}

send_user "Interface \[eth0\]: "
expect_user -re "(.*)\n"
set iface $expect_out(1,string)
# Use eth0 as the default interface if none is given
if { $iface == "" } {
  set iface "eth0"
}

send_user "Path to 'grep' \[\/bin\/grep\]: "
expect_user -re "(.*)\n"
set gpath $expect_out(1,string)
# Use /bin/grep as the default path to grep if none is given
if { $gpath == "" } {
  set gpath "/bin/grep"
}

set ifcmd "$ifpath $iface | $gpath bytes"

send_user "Interval in seconds \[1\]: "
expect_user -re "(.*)\n"
set delay $expect_out(1,string)
# Use 1 second as the default intrace polling intrval if no value is giving
if { $delay == "" } {
  set delay 1
}
send_user "\n"

#match_max 10000 # Pump up the match_max incase of large MOTD/Banners
# Connect to the host and login
spawn ssh $host -l $user -p $sshport
# Expect "assword:" as the 'p' in 'password' could be upper or lower case
expect "assword:"
send "$pass\r"
expect "$ "
puts ""

# From this point on we shall disable user output or they will see the "show int x"
# command output constantly
log_user 0

# Grab the current in/out bytes before we start the loop, to get a starting figure
send "$ifcmd\r"
expect "$ "

set ifbytes [open "ifbytes" "w"]
puts $ifbytes $expect_out(buffer)
close $ifbytes

set inbytesnow [exec grep "RX" ifbytes | cut -d : -f 2 | cut -d \  -f 1]
set outbytesnow [exec grep "RX" ifbytes | cut -d : -f 3 | cut -d \  -f 1]

set inbyteslast $inbytesnow
set outbyteslast $outbytesnow

# These variables will be presented at the end of the script when the below
# SIGINT handler is called
set totalinbytes 0
set totaloutbytes 0
set duration 0

# Here we will define a SIGINT handler, to catch the death of the script
# On exiting we shall pring out some session stats
proc sigint_handler {} {
  set inmegabytes [expr "$::totalinbytes" / 1000 / 1000]
  set outmegabytes [expr "$::totaloutbytes" / 1000 / 1000]
  puts "\nTotal duration $::duration seconds"
  puts "Total bytes received $::totalinbytes ($inmegabytes MBs)"
  puts "Total bytes sent $::totaloutbytes ($outmegabytes MBs)"
  puts "Average speed (bytes over duration)"
  set averagein [expr "$::totalinbytes" / "$::duration" / 1000 * 8]
  set averageout [expr "$::totaloutbytes" / "$::duration" / 1000 * 8]
  puts "In: $averagein Kbps \nOut: $averageout Kbps"
  exit
}
trap sigint_handler SIGINT

# Enter a continuous loop grabbing the number of bytes that
# have passed through an interface, each second.
# The different in this number each cycle, is essentially
# how much traffic this interface is pushing.

while { true } {
  send "$ifcmd\r"
  expect "$ "

  set ifbytes [open "ifbytes" "w"]
  puts $ifbytes $expect_out(buffer)
  close $ifbytes
  set inbytesnow [exec grep "RX" ifbytes | cut -d : -f 2 | cut -d \  -f 1]

  # Declare $diff outside of the if statements
  set diff 0

  if { $inbytesnow > $inbyteslast } {
    set diff [expr $inbytesnow - $inbyteslast]
    set bps [expr "$diff" \* 8]
    set kbps [expr "$bps" \/ 1000]
    set kbps [expr "$kbps" \/ "$delay"]
  } elseif { $inbytesnow < $inbyteslast } {
    set diff [expr $inbyteslast - $inbytesnow]
    set bps [expr "$diff" \* 8]
    set kbps [expr "$bps" \/ 1000]
    set kbps [expr "$kbps" \/ "$delay"]
  } elseif { $inbytesnow == $inbyteslast } {
    set diff 0
    set kbps 0
  }

  # Keep a tally of the total bytes received for a stats dump at the end
  set totalinbytes [expr "$totalinbytes" + "$diff"]

  set inbyteslast $inbytesnow
  set inkbps $kbps

  set outbytesnow [exec grep "RX" ifbytes | cut -d : -f 3 | cut -d \  -f 1]

  if { $outbytesnow > $outbyteslast } {
    set diff [expr $outbytesnow - $outbyteslast]
    set bps [expr "$diff" \* 8]
    set kbps [expr "$bps" \/ 1000]
    set kbps [expr "$kbps" \/ "$delay"]
  } elseif { $outbytesnow < $outbyteslast } {
    set diff [expr $outbyteslast - $outbytesnow]
    set bps [expr "$diff" \* 8]
    set kbps [expr "$bps" \/ 1000]
    set kbps [expr "$kbps" \/ "$delay"]
  } elseif { $outbytesnow == $outbyteslast } {
    set diff 0
    set kbps 0
  }

  # Keep a tally of the total bytes sent for a stats dump at the end
  set totaloutbytes [expr "$totaloutbytes" + "$diff"]

  set outbyteslast $outbytesnow
  set outkbps $kbps

  puts "Input: $inkbps Kbps Output: $outkbps Kbps\r"

  # Keep a record of the duration of this script for the stats dump at the end
  set duration [expr "$duration" + "$delay"]

  sleep $delay
} 
[email protected]:~/scripts$ ./expect-server.sh 
Hostname: test-server.data.net
Username: user1
Password: 
SSH port [22]: 2222
Path to 'ifconfig' [/sbin/ifconfig]: 
Interface [eth0]: eth1
Path to 'grep' [/bin/grep]: 
Interval in seconds [1]: 

spawn ssh test-server.data.net -l user1 -p 2222
[email protected]'s password: 
Linux node1 2.6.32-5-686 #1 SMP Mon Oct 3 04:15:24 UTC 2011 i686

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
You have new mail.
Last login: Tue Mar  6 10:16:01 2012 from remote.net
[email protected]:~$ 
Input: 4 Kbps Output: 55 Kbps
Input: 74 Kbps Output: 1266 Kbps
Input: 68 Kbps Output: 1239 Kbps
Input: 71 Kbps Output: 1237 Kbps
Input: 66 Kbps Output: 1235 Kbps
Input: 71 Kbps Output: 1251 Kbps
Input: 69 Kbps Output: 1240 Kbps
Input: 71 Kbps Output: 1258 Kbps
Input: 76 Kbps Output: 1262 Kbps
Input: 68 Kbps Output: 1237 Kbps
Input: 67 Kbps Output: 1243 Kbps
^C
Total duration 11 seconds
Total bytes received 88704 (0 MBs)
Total bytes sent 1566087 (1 MBs)
Average speed (bytes over duration)
In: 64 Kbps 
Out: 1136 Kbps