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.

WinEunuuchs2Unix
  • 99,709
  • 34
  • 237
  • 401

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

WinEunuuchs2Unix
  • 99,709
  • 34
  • 237
  • 401
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.

Teemu Toivola
  • 614
  • 5
  • 6
  • Had I not customized `vnall` as a wrapper to `vnstat` this would have been the accepted answer. I had tried `-i wlp60s0 enp59s0` and `-i wlp60s0 enp59s0` without success . I also tried the `vnstat --help` option and google search without success. I wish I had thought of checking manpage though! I should point out your solution is likely more accurate if it adds 512 MiB from one interface to 1 GiB to another to reach 1.5 GiB. My code isn't as granular and currently reports only 1.0 G. – WinEunuuchs2Unix Sep 07 '19 at 15:27
  • As the `vnstat` command does the data merging internally, there's no loss of resolution and it's not limited to the summary output. The `--help` output also points out the existence of the man page on the last line. Due to the number of different option combination vnStat has, it hasn't for a long time been practical to list all options in the `--help` output. Even `--longhelp` needs to try to keep some balance between output length and readability. – Teemu Toivola Sep 07 '19 at 22:04
  • Yes I read the last line of `--help` reference to manpage this morning and believe me I'm kicking myself for not seeing it sooner :( – WinEunuuchs2Unix Sep 07 '19 at 22:11