Speedtest on the Pi 3
There is a lot of talk about logging the performance delivered by our internet service providers.
Several authors have connected the utility speedtest to public logging sites, or to Google Drive to provide away from home access.
My interest is more to the personal information level, so wanted a log to look at and a basic summary over time of average, minimum, and max download speed.
This is how I got there - which included learning an awk programming trick no one else seemed to need.
To start I followed some of the steps at http://makezine.com/projects/send-ticket-isp-when-your-internet-drops/ "Use Raspberry Pi to Measure Broadband Speeds to Hold Your ISP Accountable."
I am using Raspbian-lite which did not have git-core installed.
(my first attempt at installing git-core failed so first I tried updating, and with that also failing, I discovered I needed to change mirror repository)
$ sudo apt-get update (also failed)
(So I changed /etc/apt/sources.list
to be http://raspbian.mirrors.wvstateu.edu/raspbian/
and re-ran sudo apt-get update successfully.)
Now to continue where I started, to install git-core:
sudo apt-get install git-core
(if you need a free git account, visit https://github.com/pricing and click Join for Free)
It needs to be configured with your github credentials:
$ git config --global user.name "your_git_username"
$ git config --global user.email food@bar
Now get an extension that formats a speedtest output:
$ git clone https://github.com/HenrikBengtsson/speedtest-cli-extras.git
Try it out
$ cd speedtest-cli-extras/bin
$ ./speedtest-csv
2016-05-05 22:28:01;2016-05-05 22:28:42;My Cable ISP;XX.XX.XX.XX;Hosted (City);86.24 km;41.571 ms;6.87 Mbit/s;0.00 Mbit/s;
The 7th semi-colon separated field is the ping response which I have never worried about.
The 8th field is the download speed, and the 9th is the upload speed.
My interest is in that 8th field, the download speed.
Next I set up a shell script that will run the speedtest-csv and log the results to a file:
$ cd ~ (to get back to the pi home directory)
$ nano ~/speedtest-chron.sh:
#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
/home/pi/speedtest-cli-extras/bin/speedtest-csv >> /home/pi/speedtest.log
(cntrl-o, enter, cntrl-x)
(the big path smt is to fix cron output in speedtest.log like
<date-time>;;;;;;;;;
and /etc/mail/pi that says line 132 command not found )
Now change the permission on the shell script so cron will be able to run it:
$ chmod 777 speedtest-chron.sh
Test it out:
$ ./speedtest-chron.sh (that's dot slash and then the script
Make sure speedtest.log exists:
$ ls speedtest.log
And make sure the first run was a success:
$ more speedtest.log
Next, try editing the cron table.
$ crontab -e
If this is the first time editing the crontab, it may ask what editor you want to use - choose nano.
Exit now with ctrl-x.
Now add the speedtest-chron.sh script to the cron table to be run every hour:
$ crontab -e (add the following line at the end of the file)
0 * * * * /home/pi/speedtest-chron.sh
(cntrl-o, enter, cntrl-x)
At the top of the hour, you can check what chrontab is doing with
grep CRON /var/log/syslog
If you see an error about MTA:
$ sudo apt-get install postfix
choose local only for the mails.
Now an awk script to analyze the speedtest.log:
$nano ave-speed.awk
BEGIN {
FS=";"
min=100.0
max=0.0
}
{
sub(/ Mbit\/s/,"",$8)
if ($8>0) {
$8=sprintf("%06.2f",$8);
sum += $8;
n++;
if (max<$8) max=$8;
if (min>$8) min=$8;
}
}
END {
ave=sum/n;
printf("Dnld ave:%.1f max:%.1f min:%.1f Mbit/s in %d samples\n",ave,max,min,n)
}
Awk is a very powerful, standard Linux community utility that processes text files a line at a time. It is great for files that have data in "columns" / fields separated by a common field separator such as semi-colon in the case of the speedtest-csv output.
The awk script has a begin section, an "every line" section, and an end section. I set the field separator and initialize the variables in the begin section. (Yes I know variables start with 0 value in Awk - shoot me.)
Next I strip off the label from the download speed in the 8th column/field using substitution with a null string.
I only want to use lines which have a valid download measurement, so if field 8 is not zero, I get to work.
This first line inside the if block is the trick I needed to make the min and max values work when comparing a speed with a small first of two digit speed against a larger first and only digit speed - e.g. 12.5 > 9.5.
Run this to see it fail:
$ echo "why" | awk '{a="12.5";b="9.5"; print (a > b)}'
0
and this to see how the sprintf fixes it:
$ echo "why" | awk '{a="012.5";b="009.5"; print (a > b)}'
1
So let's give the awk script a try:
$ awk -f ave-speed.awk speedtest.log
Dnld ave:15.6 max:15.6 min:15.6 Mbit/s in 1 samples
(or after three hours or three manual runs of ./speedtest-chron.sh)
For the ave,min,max in the last three runs:
tail -3 speedtest.log | awk -f ave-speed.awk
Dnld ave:19.6 max:21.4 min:16.8 Mbit/s in 3 samples
To make it less to remember: make a shell script ave-speed.sh:
$ nano ave-speed.sh
awk -f ave-speed.awk speedtest.log
(cntl-o, enter, cntl-x)
Change the script to executable:
$ chmod 777 ave-speed.sh
And try it out:
$ ./ave-speedtest.sh
Dnld ave:19.6 max:21.4 min:16.8 Mbit/s in 3 samples
Now to go to sleep and wake to:
$ ./ave-speedtest.sh
Dnld ave:15.6 max:28.0 min:3.1 Mbit/s in 11 samples
*** Alan ****