ethered has asked for the wisdom of the Perl Monks concerning the following question:

Hi all!

For some time now my internet connection have been unreliable to say the least. I'm paying for a 50/50 connection, but I'm seeing a steady 23/18 on average(mbps). As well as some pretty annoying latency issues... So! I want to monitor this over time, to build a waterproof case for myself.

I want to use speedtest-cli on my Ubuntu server, and by cron make it do a speedtest every 12 hours. After asking internet for advice I ended wanting to do this with Perl.

This is my script so far...
open speedtest,"speedtest-cli --simple |" or die "Cannot open speedtes +t"; $datestring = localtime(); while (<speedtest>) { if (/Download\:[0-9\.]*)/) { $speed=$1; print "$datestring : Download $speed +n"; } elsif (/Upload\:[0-9\.]*)/) { $speed=$1; print "$datestring : Upload $speed +n"; } }

...which works fine except for the fact that it doesn't print the results, rather just time/date and "Download"/"Upload".

It works like a charm on AIX, but not on Ubuntu. Why?

Also; I want to store this in one .txt file, and I'm thinking that I'll do that in my crontab. Would it store each result in a new line in that file or overwrite it? Any ideas on how to do this?

Thank you for any and all help regarding this :-) PS: I can verify that the script starts speedtest-cli, and that it prints out time/date.

Replies are listed 'Best First'.
Re: Running speedtest-cli with Perl and cron
by Anonymous Monk on Dec 11, 2014 at 16:17 UTC

    The capture group in the regex is missing an open paren, e.g. /Download\:([0-9\.]*)/ (although I might suggest something like /Download:\s*(\S+)/ to make it a little bit more flexible if the program's output varies). You say it works on AIX, I'm a little unsure how that's possible...

    On Ubuntu, is cron emailing any error messages to the crontab's user? What error messages do you get running this from the command line (not from the crontab)?

    You really should be using warnings and strict!

    Also, there are modules that can help you capture the output of external programs, such as Capture::Tiny, IPC::System::Simple or IPC::Run3.

    You can either have the script write to an output file, or do it from the crontab using shell redirection - in either case you can append to the output file using >> instead of >.

      Yes! Your suggestion for the if-statement works like a charm!

      The script ran just as it should before as well, it just didn't give me the results from the test. Which is strange because it did so on the AIX system at work. The only thing not printing to screen is the up/down values.

      Since I started mucking around with Perl only days ago I'm not very aware of how to really do stuff. I will definitely look into warnings and strict, and perhaps look for a smarter way of building it without the if-elsif.

      Thanks for the help! :-)

      Oh, btw... Here's the output using your statements:

      Fri Dec 12 07:30:00 2014 : Download 47.82 Fri Dec 12 07:30:00 2014 : Upload 10.28
Re: Running speedtest-cli with Perl and cron
by GotToBTru (Prior) on Dec 11, 2014 at 16:13 UTC

    Does this code compile on your machine? Your two regexes contain unbalanced parentheses.

    1 Peter 4:10

      Yes, it runs without problems. I'm using tmux from work, so copy/paste from it doesn't really work that well. I probably just wrote it down wrong while using notepad.

Re: Running speedtest-cli with Perl and cron
by Tux (Canon) on Dec 12, 2014 at 09:44 UTC

    Why use speedtest-cli (written in python) when a perl version that can do more exists?

    I wrote speedtest in perl because the author of speedtest-cli is not very open to new suggestions (and because python sucks).

    $ speedtest --help usage: speedtest [ --no-geo | --country=NL ] [ --list | --ping ] [ opt +ions ] --geo use Geo location (default true) for closest test +server --all include *all* servers (default only in own count +ry) -c --country=IS use ISO country code for closest test server -1 --one-line show summary in one line -l --list list test servers in chosen country sorted by di +stance -p --ping list test servers in chosen country sorted by la +tency --url show server url in list -s --server=nnn use testserver with id nnn --url=sss use specific server url (do not scan) ext php --mini=sss use specific server url (do not scan) ext from s +ss --download test download speed (default true) --upload test upload speed (default true) -q --quick[=20] do a quick test (only the fastest 20 tests) -Q --realquick do a real quick test (only the fastest 10 tests) -T --try[=5] try all tests on the n fastest servers -v --verbose[=1] set verbosity --simple alias for -v0 --ip show IP for server -V --version show version and exit -? --help show this help speedtest --list speedtest --ping --country=BE speedtest speedtest -s 4358 speedtest --url=http://ookla.extraip.net speedtest -q --no-download speedtest -Q --no-upload $ speedtest Testing for 1.1.1.1 : XS4ALL Internet BV (NL) Using 4358: 53.18 km 50 ms KPN Test download ........................................Download: 93.8 +29 Mbit/s Test upload ........................................Upload: 117.2 +57 Mbit/s $ speedtest -1v0 DL: 93.877 Mbit/s, UL: 116.910 Mbit/s

    Enjoy, Have FUN! H.Merijn
      ++ for your speedtest Tux!! just tried and i'm very happy with it.
      L*
      There are no rules, there are no thumbs..
      Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: Running speedtest-cli with Perl and cron
by NetWallah (Canon) on Dec 12, 2014 at 07:01 UTC
    Thanks for introducing me to the Speedtest CLI.

    Here;s my contribution - this code returns a comma-separated list that can eventually be graphed by a spreadsheet program.

    use strict; use warnings; open my $speedtest,"speedtest-cli --simple |" or die "Cannot open spee +dtest:$!"; my %speed = (DATETIME => '"' . GetDateTime()->{datetime} . '"'); while (<$speedtest>) { next unless m/(\w+): ([\d\.]+)/; $speed{$1} = $2; } close $speedtest; print join(",",map {$speed{$_}} qw|DATETIME Download Upload|),"\n"; sub GetDateTime{ local $_={}; @$_{qw|sec min hour mday mon year wday yday isdst|} =localtime(tim +e); $_->{year}+=1900; $_->{mon}+=1; $_->{yyyymmdd} = sprintf "%04d-%02d-%02d", @$_{qw|year mo +n mday|}; $_->{hhmm} = sprintf "%02d:%02d", @$_{qw|hour mi +n|}; $_->{datetime} = $_->{yyyymmdd} . " " . $_->{hhmm}; return $_ }
    Output:
    "2014-12-11 22:58",53.79,7.19

            "You're only given one little spark of madness. You mustn't lose it."         - Robin Williams

      Cool!

      I like the use of print join and I will add this to my script.

      This is the crontab line I use for appending the results in the same file, I also added an \n to my script to make a new line for each test. I don't see the need for throwing this into a .csv or such, so the notepad will suffice.

      What's the best practice for writing to file? Should the file be written by the script, or is it okay to do this with crontab?

      * */12 * * * /usr/bin/perl /bin/speedtest.pl >> /storage/documents/cron/speedtest/speedtest.txt 2>&1

      You guys are awesome! I've never encountered a forum where people answer this fast, and all the response is helpful. I'm going to be a lot on this website henceforth :-)

        ... best practice for writing to file
        My preference is for the program/script to send output to STDOUT. Externally (as you have done it), this is directed to a user-specified location, which could well be a socket to a different machine, plumbed into a pipe, or dispersed somewhere cloudy or smoggy.

                "You're only given one little spark of madness. You mustn't lose it."         - Robin Williams

Re: Running speedtest-cli with Perl and cron
by Discipulus (Canon) on Dec 12, 2014 at 09:23 UTC
    As NetWallah said, thanks for the speedtest-cli information.

    I propose you another solution, even if not intended to measure the whole line speed but the speed of web access, and produces, if told, one line per access. At least you can compare results to further analyze your line degradation. You can find my WebTimeLoad0.23.pl here. You can use -v, -s and -c to bend it at your needs.

    # -c --count how many times repeat the check. default is 1 # -s --sleep seconds between checks. default is 1. # -v --verbosity from 0 (one line output for each check) to 3. defa +ult 1 webTimeLoad23.pl -u www.perlmonks.org -v 0 -c 1000 -s 60 Fri Dec 12 10:15:46 2014 http://www.perlmonks.org 200 + 116076 2.335208 48.5419 Kb/s Fri Dec 12 10:16:48 2014 http://www.perlmonks.org 200 + 116076 1.913632 59.2358 Kb/s Fri Dec 12 10:17:50 2014 http://www.perlmonks.org 200 + 116076 1.798926 63.0129 Kb/s Fri Dec 12 10:18:52 2014 http://www.perlmonks.org 200 + 116316 1.816933 62.5174 Kb/s

    As side note i found this article about speed tests.
    HtH
    L*
    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.