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.
Top comments (5)
Thanks! Worth noting that if your default shell is not bash, this may not work, but adding in
#!/bin/bash
to the top will instruct bash to execute the rest of the script.I note this because I was scratching my head for a minute or two trying to figure out why it wasn't working - ha.
Oh sorry for that! 🙏 I tried to keep the code easy and clean lol.
Oh nothing to be sorry about at all, it was just in case someone else had the same issue. Most folks will be using bash, and if they're not, will probably be aware of what to do! (:
In such a manner, but in pair with aosd_cat (man: displays text on the screen) I get my local temp (t°) warning (⚠) right on screen when heat is too high. It appears ss a prompt notice to handle particular process just in time. But conky (man: system monitor for X originally based on the torsmo code) very long time do for me what you want to achieve.
Excelent post!! Thanks!
Also, if you ever need to test the max transfer speed between machines on your network you can use iperf/iperf3. It's cross-platform and very easy to use :)