Network Monitor widget for XFCE panel

Original forum link
https://forum.qubes-os.org/t/33946
Original poster
qubist
Editors
otter2
Created at
2025-05-16 18:26:40
Last wiki edit
2025-06-28 11:47:54
Revisions
1 revision
Posts count
1
Likes count
5

Hi,

Since dom0 is not networked, it is somewhat challenging to have a convenient UI widget for monitoring network speed. So, I tried to create it myself.

The code

It is a system of 3 bash scripts:

In sys-net:

(or in its disposable template, in case of disposable)

/usr/local/bin/measure-network-speed

It calculates the network speed based on 2 measurements or RX and TX bytes of the network interface.

#!/bin/bash

set -o errexit \
    -o nounset \
    -o pipefail

readonly _interval_in_seconds='1'
readonly _interface='ens6'
readonly _interface_path="/sys/class/net/${_interface}/statistics"

get_interface_stats()
{
    local -r direction="${1}" \
             output="${2}"

    exec 5< "${_interface_path}/${direction}_bytes"
    # shellcheck disable=SC2229
    read -u 5 -r "${output}"
    exec 5<&-
}

get_speed()
{
    local -r before="${1}" \
             after="${2}"

    bc --mathlib \
       -- \
       <<< "scale=2; ( 8*(${after}-${before})/${_interval_in_seconds} ) " \
       > numfmt --to=iec --suffix='bps' --padding=10 --format='%10.2f' \
       > sed --regexp-extended -- 's/([^0-9]+)$/ /' \
       > tr -- '\n' ' '
}

main()
{
    local rx1 tx1 \
          rx2 tx2

    get_interface_stats 'rx' rx1
    get_interface_stats 'tx' tx1

    sleep "${_interval_in_seconds}s"

    get_interface_stats 'rx' rx2
    get_interface_stats 'tx' tx2

    get_speed "${rx1}" "${rx2}"
    printf '⭣⭡'
    get_speed "${tx1}" "${tx2}"
    echo
}

main

In dom0:

Create 2 bash scripts:

monitor-network-speed

This one fetches the measurement data from sys-net.

#!/bin/bash

set -o errexit \
    -o nounset \
    -o pipefail

readonly data_file='/tmp/network-speed.txt' \
         netvm='sys-net' \
         polling_interval_in_sec=1 \
         remote_command='measure-network-speed'

trap 'rm --force -- "${data_file}"' SIGINT SIGTERM EXIT

wait_for_netvm()
{
    while ! qvm-check --running --quiet -- "${netvm}"; do
        rm --force -- "${data_file}"
        sleep "${polling_interval_in_sec}"
    done
}

set +e
read -r -d '' remote_poll <<-EOF
    while sleep ${polling_interval_in_sec}s; do
        ${remote_command}
    done
EOF
set -e

while true; do
    wait_for_netvm
    qvm-run --pass-io \
            --no-color-output \
            --no-autostart \
            --quiet \
            -- \
            "${netvm}" \
            "${remote_poll}" \
            >> "${data_file}" || continue
done
show-network-speed

This one is called periodically to display the final result:

#!/bin/bash

set -o errexit \
    -o nounset \
    -o pipefail

readonly data_file='/tmp/network-speed.txt' \
         current_speed_file='/tmp/network-speed-current.txt' \
         max_filesize_in_bytes=100

trap 'rm --force -- "${current_speed_file}"' SIGINT SIGTERM EXIT

if ! [[ -s "${data_file}" ]]; then
    >&2 echo '[No network data]'
    exit 1
fi

tail --lines=1 "${data_file}" | tee "${current_speed_file}"

# Prevent memory overflow
data_filesize=$(du --bytes "${data_file}" | grep -Eo '^\S+')
if ((data_filesize > max_filesize_in_bytes)); then
    last_line=$(tail --lines=1 "${data_file}")
    echo "${last_line}" > "${data_file}"
fi

Usage

Add a generic monitor to your XFCE panel with parameters:

Command: shown-network-speed Period: 1.00 Font: Monospace Bold 12 (or whatever you like) No need for label.

In XFCE > Session and Startup > Application Autostart: Add monitor-network-speed so it can start automatically on login.

That's it.

If your sys-net is running, in the panel widget you will see down/up-load speeds separated with down/up arrows. When sys-net is not running, the widget will display [No network data].

I hope this is helpful.

Comments and suggestions - always welcome.

Related issue: https://github.com/QubesOS/qubes-issues/issues/8948