Build a network speed monitor in bash with AWK
Axel Navarro
Posted on January 6, 2021
Sometimes we need to measure the network speed of a server, but services like speedtest
are not useful because we want to check our bandwidth against another cloud service and not the internet itself.
AWK to the rescue
We can write a simple script in AWK to parse the /proc/net/dev
pseudo-file which contains network device status information. AWK is a programming language to manipulate columns of data that we can't solve with a simple sed
command and a regex.
But before talking about the AWK script, we should define the sentences in bash that we need in this script. Or, you can jump to the end to find the complete script 😁.
The bash side
We need to create a .sh
file with an infinite loop to print the network speed every 2 seconds.
INTERFACE=eth0
echo "$INTERFACE down (KiB/s) up (KiB/s)"
while :
do
# The AWK command here!
sleep 2;
done
First, we declare the variable INTERFACE
with the name of the network interface to be inspected - in this example is eth0
.
Then, we print a nice header to remind ourselves which column is the download speed (and the upload one). These speeds are measured in kilobytes per second (KiB/s, the i
is because 1 Kibibyte is 1024 bytes).
Finally, we start the infinite loop with a sleep of 2 seconds between iterations. Don't worry, this script can be stopped using Ctrl+C
.
Comparing the dev pseudo-file in time
We want to measure the network speed in KiB per second, so we should read the /proc/net/dev
file and compare it against a new read from the same file after 1 second. For this, we can use a little bash trick called process substitution.
awk '...' \
<(grep $INTERFACE /proc/net/dev) \
<(sleep 1; grep $INTERFACE /proc/net/dev)
We use grep
to read the line of our interface, and after waiting for 1 second we must read the line of our interface again.
The AWK script
If we check the output of /proc/net/dev
cat /proc/net/dev
We'll see that the 1st column is the interface name, the 2nd column is the received bytes (rx
) and the 10th column is the transmitted bytes (tx
).
We should save the first read in the rx
and tx
variables, and then print
the difference between the 2nd read and the first one. But, we could divide the result by 1024 because KiB/s is a better human readable format than B/s.
{
if (rx) {
print " "($2-rx)/1024" "($10-tx)/1024
} else {
rx=$2; tx=$10;
}
}
We can see its output by running:
$ ./net-monitor.sh
eth0 down (KiB/s) up (KiB/s)
0.123047 0.0683594
5.38086 6.18457
1132.12 70.1748
If we want to round the decimal part we can use the printf
function.
{
if (rx) {
printf(" %.0f %.0f\n", ($2-rx)/1024, ($10-tx)/1024)
} else {
rx=$2; tx=$10;
}
}
The bash script
This is our final bash script
echo "$INTERFACE down (KiB/s) up (KiB/s)"
while :
do
awk '{
if (rx) {
printf (" %.0f %.0f\n", ($2-rx)/1024, ($10-tx)/1024)
} else {
rx=$2; tx=$10;
}
}' \
<(grep $INTERFACE /proc/net/dev) \
<(sleep 1; grep $INTERFACE /proc/net/dev)
sleep 2;
done
And it's ready! Just open a terminal and run the script to monitor the network speed while you're running your network process.
Posted on January 6, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.