2

My laptop has two network interfaces enp59s0 and wlp60s0. Historically I've always used the Ethernet card (enp59s0) so using vnstat to get network consumption for today, yesterday, current week and current month has never been an issue with me.

Recently I've moved and now I'll be using WiFi (wlp60s0). I had to modify my conky code:

${color}${goto 5}Today ${goto 100}Yesterday ${goto 225}Week ${goto 325}Month ${color green}
# vnstatd updates database every five minutes
${execi 300 vnstat -i wlp60s0 | grep "today" | awk '{print $8" "substr ($9, 1, 1)}'} ${goto 110}${execi 300 vnstat -i wlp60s0 | grep "yesterday" | awk '{print $8" "substr ($9, 1, 1)}'} ${goto 220}${execi 300 vnstat -i wlp60s0 -w | grep "current week" | awk '{print $9" "substr ($10, 1, 1)}'} ${goto 315}${execi 300 vnstat -i wlp60s0 -m | grep "`date +"%b '%y"`" | awk '{print $9" "substr ($10, 1, 1)}'}

It is awkward for me to change conky calls to vntstat so I would like both wlp60s0 and enp59s0 combined together with a bash script. I prefer bash as it is easier for me to maintain. The script is called every 5 minutes so performance impact is nominal.

Not only does would a script save me from changing Conky code dependent on interface, but ISP monthly quota will be accurately tracked with both interfaces added together.

I prefer a bash script to solve this problem but other readers might be interested in C, Java or Python solutions.

2 Answers2

4

This bash script will add up vnstat totals for multiple interfaces:

#!/bin/bash

# NAME: vnall
# DESC: Add up multiple interfaces of vnstat into totals for today,
#       yesterday, current week and current month.
# PARM: "today", "yesterday", "week" (current), "month" (current)
# DATE: September 2, 2019. Modified September 4, 2019.

# To discover interfaces `lshw -c network` then place names below
# aInterfaces=( "enp59s0" "wlp60s0" )
# Use automatic discovery if you are unsure of names or don't want to look up
Interfaces=( $(lshw -c network 2>/dev/null | grep name: | cut -d':' -f2) )

Tally () {
    Ktot=0     # Totals in KiB, MiB and GiB
    Mtot=0
    Gtot=0
    # Tally all interfaces
    local i Interface Line Raw ThisNum
    for (( i=0; i<${#aInterfaces[@]}; i++ )) ; do

        Interface="${aInterfaces[i]}"
        if [[ "$vnstatParm" == "" ]] ; then
            Line=$(vnstat -i "$Interface" | grep "$GrepString")
        else
            Line=$(vnstat -i "$Interface" "$vnstatParm" | grep "$GrepString")
        fi

        [[ $Line == "" ]] && continue   # No data collected yet
        if [[ $vnstatParm == "" ]] ; then
            Raw=$(echo "$Line" | awk '{print $8 substr ($9, 1, 1)}')
        else
            Raw=$(echo "$Line" | awk '{print $9 substr ($10, 1, 1)}')
        fi

        ThisNum="${Raw::-1}"    # Number without suffix
        case ${Raw: -1} in      # Decide on last character K, M or G
            K)
                Ktot=$(echo "$Ktot + $ThisNum " | bc) ;;
            M)
                Mtot=$(echo "$Mtot + $ThisNum " | bc) ;;
            G)
                Gtot=$(echo "$Gtot + $ThisNum " | bc) ;;
            *)
                echo "Unknown Unit: ${Raw: -1}" ;;
        esac
    done

    [[ $Gtot != "0" ]] && { echo "$Gtot G" ; return ; }
    [[ $Mtot != "0" ]] && { echo "$Mtot M" ; return ; }
    [[ $Ktot != "0" ]] && { echo "$Ktot K" ; return ; }
    echo "N/A"
} # Tally

Init () {
    GrepString="$1"     # Create defaults for "today" and "yesterday"
    vnstatParm=""
    if [[ $1 == week ]] ; then
        GrepString="current $GrepString"
        vnstatParm="-w"
    fi
    if [[ $1 == month ]] ; then
        GrepString=$(date +"%b '%y")
        vnstatParm="-m"
    fi
} # Init

Init "$@"
Tally

Automatic vs Manual interface names

Notes this section of code:

# To discover interfaces `lshw -c network` then place names below
# aInterfaces=( "enp59s0" "wlp60s0" )
# Use automatic discovery if you are unsure of names or don't want to look up
Interfaces=( $(lshw -c network 2>/dev/null | grep name: | cut -d':' -f2) )

The fourth line automatically discovers the interface names (in my case enp59s0 and wlp60s0) and builds the array of interfaces (aInterfaces). If you prefer to manually specify the names in your script then place a comment (#) at the beginning of the line and uncomment the second line by removing the # line prefix.

Conky code shrinks considerably

Because the new vnall script automatically creates parameters as needed, the conky code is a lot smaller than before:

${color}${goto 5}Today ${goto 100}Yesterday ${goto 225}Week ${goto 325}Month ${color green}
# vnstatd updates database every five minutes
${execi 300 vnall "today"} ${goto 110}${execi 300 vnall "yesterday"} ${goto 220}${execi 300 vnall "week"} ${goto 315}${execi 300 vnall "month"}

Conky Image

vnall.png

1

The vnstat command supports merging interface data internally using the + syntax as explained by the man page:

-i, --iface interface
       Select one specific interface and apply actions to only it. For queries, it is possible to merge the information of two or
       more interfaces using the interface1+interface2+...  syntax.

In your case, it's enough to replace -i wlp60s0 with -i wlp60s0+enp59s0.