2

I need to calculate the average network traffic on an interface. I know about software like iftop, but I cannot use it in my case.

I am running a program which shall do calculations with the average network traffic on an interface. Therefore, I require a command which produces a simple output. Programs like iftop output the values in a very complex way which cannot be easily parsed by other applications.

I am looking for something like:

Command:

$ get-avg-traffic --interface=eth0 --seconds-interval=30 --type=incoming --unit=KB

Output:

783846

Is there already software which supports (some of) this functionality?

3

You probably want to have a look at vnstat

$ vnstat -d -i wlp3s0

wlp3s0  /  daily

     day         rx      |     tx      |    total    |   avg. rate
 ------------------------+-------------+-------------+---------------
 2017-10-24   166,63 MiB |   37,33 MiB |  203,96 MiB |   19,34 kbit/s
 2017-10-25   214,68 MiB |  130,26 MiB |  344,94 MiB |   32,71 kbit/s
 2017-10-26     1,01 GiB |    4,09 GiB |    5,10 GiB |  495,31 kbit/s
 2017-10-27     1,16 GiB |  113,28 MiB |    1,27 GiB |  123,04 kbit/s
 2017-10-28   201,09 MiB |  299,21 MiB |  500,31 MiB |   47,44 kbit/s
 2017-10-29     1,92 GiB |  174,35 MiB |    2,09 GiB |  202,92 kbit/s
 2017-10-30   559,56 MiB |   69,18 MiB |  628,73 MiB |   59,61 kbit/s
 2017-10-31   397,73 MiB |   43,62 MiB |  441,35 MiB |   41,85 kbit/s
 2017-11-01   665,81 MiB |   83,05 MiB |  748,86 MiB |   71,00 kbit/s
 2017-11-02   282,20 MiB |  239,91 MiB |  522,11 MiB |   49,50 kbit/s
 2017-11-03     4,06 GiB |    4,85 GiB |    8,92 GiB |  865,61 kbit/s
 2017-11-04   220,95 MiB |   40,12 MiB |  261,07 MiB |   24,75 kbit/s
 2017-11-05   320,91 MiB |    8,86 GiB |    9,18 GiB |  890,93 kbit/s
 2017-11-06   639,67 MiB |   13,77 GiB |   14,39 GiB |    1,40 Mbit/s
 2017-11-07   694,91 MiB |   80,48 MiB |  775,39 MiB |   73,52 kbit/s
 2017-11-08   178,64 MiB |   32,43 MiB |  211,07 MiB |   28,97 kbit/s
 ------------------------+-------------+-------------+---------------
 estimated       257 MiB |      46 MiB |     303 MiB |

You can have hourly daily and monthly statistics.

2

The command ip (formerly netstat) will give you this type of information but you'll need to do parsing to get just a number AFAICT (I'm no expert on it).

localhost-$ ip -s -h -c link show wlan15

gives output like:

3: wlan15: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1372 qdisc mq state UP mode DORMANT group default qlen 1000
    link/ether a0:f3:c1:28:2b:68 brd ff:ff:ff:ff:ff:ff
    RX: bytes  packets  errors  dropped overrun mcast   
    78.2M      137k     0       0       0       0       
    TX: bytes  packets  errors  dropped carrier collsns 
    146M       197k     0       0       0       0

So for example:

ip -s -c link show wlan15 | tail -n1 | cut -d " " -f5

Would give 146013456 or somesuch, the 146M in raw bytes as the transmission volume on the particular interface. tail takes the last line (use it with head to pick an arbitrary line [there are plenty of other ways]), cut is separating that output in to fields with " " as the delimiter and choosing the fifth field.

Using this value in your program to calculate the average transmission rate should be straightforward.

2

My suggestion is the following script, based on ifconfig and one my previous answer, where are provided more explanations.

1. Create executable script file, called get-traffic, that is located in /usr/local/bin to be accessible as shell command (more detailed steps).

2. The content of the script get-traffic is:

#!/bin/bash

# Set the default values or Read the users input
[ -z "${1}" ] && IFACE="eth0"  || IFACE="$1"       # Get the name of the target interface, default: eth0
[ -z "${2}" ] && UNIT="MB"     || UNIT="$2"        # Get the unit (B, KB, MB, GB, Kib, Mib, Gib), default: MB
[ -z "${3}" ] && PERIOD="30"   || PERIOD="$3"      # Get the period of measure in seconds, default: 30
[ -z "${4}" ] && OUTPUT="verb" || OUTPUT="${4,,}"  # Get the type of the output (verbose, all, incoming, outgoing, total) in lower case, default: all
LANG=C # Set envvar $LANG to `C` due to grep, awk, etc.

# Do the conversion
if   [ "$UNIT" == "B"   ]; then UN="1"
elif [ "$UNIT" == "KB"  ]; then UN="1000"
elif [ "$UNIT" == "KiB" ]; then UN="1024"
elif [ "$UNIT" == "MB"  ]; then UN="1000000"
elif [ "$UNIT" == "MiB" ]; then UN="1048576"
elif [ "$UNIT" == "GB"  ]; then UN="1000000000"
elif [ "$UNIT" == "GiB" ]; then UN="1073741824"
else echo "Wrong UNIT."; exit 1; fi

# Whether the $PERIOD is integer
if ! [[ "$PERIOD" =~ ^[0-9]+$ ]]; then echo "Enter the PERIOD in seconds"; exit 1; fi

# Get the IP address of the interface
get_ip(){ /sbin/ifconfig "$IFACE" 2>/dev/null | grep -Po '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | head -1; }

# The main program: If the interface has IP adders it is UP
if [[ "$(get_ip)" =~ ${IPPT} ]]; then
        bRX="$(/sbin/ifconfig "$IFACE" | grep -Po "RX bytes:[0-9]+" | sed 's/RX bytes://')" # Get the incoming traffic into the Beginning of the period
        bTX="$(/sbin/ifconfig "$IFACE" | grep -Po "TX bytes:[0-9]+" | sed 's/TX bytes://')" # Get the outgoing traffic into the Beginning of the period
        bXX=$(( bRX + bTX )) # Calculate the total traffic into the Beginning of the PERIOD

        sleep "$PERIOD" # Sleep for the PERIOD, seconds

        eRX="$(/sbin/ifconfig "$IFACE" | grep -Po "RX bytes:[0-9]+" | sed 's/RX bytes://')" # Get the incoming traffic into the End of the period
        eTX="$(/sbin/ifconfig "$IFACE" | grep -Po "TX bytes:[0-9]+" | sed 's/TX bytes://')" # Get the outgoing traffic into the End of the period
        eXX=$(( eRX + eTX )) # Calculate the total traffic into the End of the PERIOD

        RX=$(awk -v e="${eRX}" -v b="${bRX}" -v un="${UN}" 'BEGIN{ print ( e - b) / un }') # Calculate the amount of the incoming traffic for the PERIOD
        TX=$(awk -v e="${eTX}" -v b="${bTX}" -v un="${UN}" 'BEGIN{ print ( e - b) / un }') # Calculate the amount of the outgoing traffic for the PERIOD
        XX=$(awk -v e="${eXX}" -v b="${bXX}" -v un="${UN}" 'BEGIN{ print ( e - b) / un }') # Calculate the amount of the total traffic for the PERIOD

        # Output
        if   [[ "$OUTPUT" =~ ^verb ]]; then printf 'Interface: %s\nUnit: %s\nPeriod of measure: %s sec.\n\nReceived: %s\nTransmited: %s\nTotal: %s\n' "$IFACE" "$UNIT" "$PERIOD" "$RX" "$TX" "$XX"
        elif [[ "$OUTPUT" =~ ^all  ]]; then printf '%s\n%s\n%s\n' "$RX" "$TX" "$XX"
        elif [[ "$OUTPUT" =~ ^in   ]]; then printf '%s\n' "$RX"
        elif [[ "$OUTPUT" =~ ^out  ]]; then printf '%s\n' "$TX"
        elif [[ "$OUTPUT" =~ ^tot  ]]; then printf '%s\n' "$XX"
        else echo "Wrong OTPUT type."; fi
else
        echo "The INTERFACE \"$IFACE\" is down."
fi

3. The script call syntax:

get-traffic <interface name> <units of measurement> <period of measure> <type of the output>
get-traffic enp0s25 MiB 30 total

4. Input parameters:

  • <interface name> use the command ifconfig to get the interface name. Default: eth0
  • <units of measurement> available values: B, KB, KiB, MB, Mib, Gb, Gib. Default: MB
  • <period of measure> in seconds. Default: 30
  • <type of the output> available values: verbose, all, incoming, outgoing, total.

5. Examples of usage:

enter image description here

2

You can get the values yourself the same way those other programs do it, by looking at the contents of e.g. /proc/net/dev or /sys/class/net/eth0/statistics/rx_bytes periodically and calculating the delta yourself.

So for your specific example,

start=$(< /sys/class/net/eth0/statistics/rx_bytes) # get received bytes
sleep 30                                           # wait 30 seconds (make this a variable in your program!)
end=$(< /sys/class/net/eth0/statistics/rx_bytes)
delta=$((end-start))                               # calculate bytes received over the period
echo $(($((delta+512))/1024))                      # roughly round to nearest 1k
2

A hard coded example using ifconfig. For longer term monitoring vnstat is more appropriate.

#!/bin/bash
INTERFACE=wlp2s0
A=($(ifconfig $INTERFACE | grep bytes | sed -e 's/[(|)]//g' -e 's/:/ /g' -e 's/  */ /g'))
sleep 30
B=($(ifconfig $INTERFACE | grep bytes | sed -e 's/[(|)]//g' -e 's/:/ /g' -e 's/  */ /g'))
echo -e ${A[@]}"\n"${B[@]}
AVG=$(expr ${B[2]} - ${A[2]})
AVGKB=$(echo AVG | awk '{ byte =$1 /1024; print byte " KB" }')
#AVGMB==$(echo AVG | awk '{ byte =$1 /1024/1024; print byte " MB" }')
#AVGMB==$(echo AVG | awk '{ byte =$1 /1024/1024/1024/; print byte " GB" }')
echo -e "30 sec average\n"$AVG"\n"$AVGKB

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.