Open29

speedtest-cliをcronで動かしてネットワーク速度のログをとる

astkastk

そういうアプリがある気もしますがせっかくなのでやってみます。

astkastk

https://www.speedtest.net を利用します。単発なら普通にウェブUIで計測できます。ここが提供している https://www.speedtest.net/apps/cli を利用してcliで計測できるようにします。

homebrew の tap が提供されているので案内の通りインストールします。ありがたいですね。

brew tap teamookla/speedtest
brew update
# Example how to remove conflicting or old versions using brew 
# brew uninstall speedtest --force
brew install speedtest --force
astkastk

インストールしたら試しに実行してみます。-f json オプションでJSONとして出力できます。

%  /usr/local/Cellar/speedtest/1.0.0/bin/speedtest -f json -u Mbps | jq

私の環境だと speedtest がPATHの通った場所にインストールされなかったのでフルパスで実行しています。何か設定を間違えているとかでしょうか。

実行すると以下のようなデータが出力されました。出力は一部マスクしています。

{
  "type": "result",
  "timestamp": "2021-05-02T05:54:31Z",
  "ping": {
    "jitter": 0.609,
    "latency": 5.267
  },
  "download": {
    "bandwidth": 11981913,
    "bytes": 163142000,
    "elapsed": 15003
  },
  "upload": {
    "bandwidth": 11771331,
    "bytes": 117455747,
    "elapsed": 9802
  },
  "packetLoss": 0,
  "isp": "xxxxxxxx",
  "interface": {
    "internalIp": "xxxxxxxx",
    "name": "en0",
    "macAddr": "xxxxxxxx",
    "isVpn": false,
    "externalIp": "xxxxxxxx"
  },
  "server": {
    "id": 15047,
    "name": "OPEN Project (via 20G SINET)",
    "location": "Tokyo",
    "country": "Japan",
    "host": "speed.open.ad.jp",
    "port": 8080,
    "ip": "202.222.12.78"
  },
  "result": {
    "id": "xxxxxxxx",
    "url": "xxxxxxxx"
  }
}
astkastk

cron に登録します。ログの場所はひとまず /var/log/speedtest にしてownerをユーザにしました。ユーザのログを置いておくのってどこにするのが良いんでしょうね。

touch /var/log/speedtest # ログを記録するファイル
chown asa-taka:staff /var/log/speedtest
crontab -e # エディタが開く

crontab -e で開いたエディタに以下の行を追加します。

*/10 * * * * /usr/local/Cellar/speedtest/1.0.0/bin/speedtest -f json >> /var/log/speedtest

これで定期実行されるようになります。

astkastk

tail -f | jq して簡易モニタリングしてみます。bandwidth の単位がわからなかったのですがウェブUIの値と比べたところ bytes/sec な雰囲気だったので Mbps (Mbits/sec) に換算します。

 tail -f /var/log/speedtest | jq '.download.bandwidth*=8/1000/1000 | { t: .timestamp, down: .download.bandwidth, up: .upload.bandwidth  }' -c

ある程度時間が経つと以下のように表示されます。

{"t":"2021-05-02T05:25:27Z","down":31.30588,"up":8613088}
{"t":"2021-05-02T05:25:57Z","down":190.825168,"up":11672426}
{"t":"2021-05-02T05:30:24Z","down":178.068232,"up":7543841}
{"t":"2021-05-02T05:40:27Z","down":145.352656,"up":11128804}
:

フレッツ光の通常プランなので200Mbpsが上限ですが、割と上限いっぱい出ている感じがしますね。NUROが気になっていますが現状でそこまで不満が無いので、生活の質の向上具合で考えるとちょっと割高感があるんですよね。

astkastk
astkastk

とりあえず homebrew でインストールする。

brew install gnuplot
astkastk

bashplotlib を pip でインストールしてみたけどこれどこにインストールされたんだ…

astkastk

hist と scatter が入っていた。

asa-taka@tailmoon ~ % pip show -v bashplotlib
Name: bashplotlib
Version: 0.6.5
Summary: plotting in the terminal
Home-page: https://github.com/glamp/bashplotlib
Author: Greg Lamp
Author-email: lamp.greg@gmail.com
License: BSD
Location: /usr/local/lib/python3.9/site-packages
Requires:
Required-by:
Metadata-Version: 2.1
Installer: pip
Classifiers:
  Environment :: Console
  Intended Audience :: End Users/Desktop
  License :: OSI Approved :: BSD License
  Programming Language :: Python :: 2.7
  Programming Language :: Python :: 3
Entry-points:
  [console_scripts]
  hist = bashplotlib.histogram:main
  scatter = bashplotlib.scatterplot:main
astkastk

jq でcsvに整形する。

asa-taka@tailmoon ~ % tail /var/log/speedtest | jq -r '.download.bandwidth*=8/1000000| [.timestamp, .download.bandwidth] | @csv'
"2021-05-02T06:50:29Z",34.85248
"2021-05-02T07:00:22Z",184.470776
"2021-05-02T07:10:35Z",132.00067199999998
"2021-05-02T07:20:34Z",111.779984
"2021-05-02T07:30:25Z",170.27248
"2021-05-02T07:40:34Z",31.727864
"2021-05-02T07:50:26Z",71.454424
"2021-05-02T08:00:33Z",130.009232
"2021-05-02T08:10:28Z",159.37851999999998
"2021-05-02T08:20:18Z",191.119744
astkastk

ちょっと改良。

asa-taka@tailmoon ~ % tail /var/log/speedtest | jq -r '[(.timestamp | fromdate), .download.bandwidth*8/1000000] | @csv'
1619938822,184.470776
1619939435,132.000672
astkastk

scatter で出力できた。

asa-taka@tailmoon ~ % cat /var/log/speedtest | jq -r '[(.timestamp | fromdate), .download.bandwidth*8/1000000] | @csv' | scatter -c blue
------------------------------------------
|       xxx x       xx|
| x    x              |
|              x      |
|    x             x  |
|                     |
|   x                 |
|                     |
|            x    x   |
|                     |
|             x       |
|                     |
|                     |
|                     |
|                     |
|                x    |
|                     |
|                     |
|     x               |
|          x          |
|               x     |
------------------------------------------

あまり見やすくはない。時刻文字列は受け取れないらしくて残念。あと目盛も出せない。

astkastk

今度は https://github.com/chriswolfvision/eplot を使ってみた。

asa-taka@tailmoon ~ % cat /var/log/speedtest | jq -r '[.download.bandwidth*8/1000000] | @csv' | eplot -d
echo '
set style line 1 lt 1 lw 1 pt 1 ps 0.5;
set style line 2 lt 3 lw 1 pt 1 ps 0.5;
set style line 3 lt 7 lw 1 pt 1 ps 0.5;
set style line 4 lt 4 lw 1 pt 4 ps 0.5;
set style line 5 lt 5 lw 1 pt 4 ps 0.5;
set style line 6 lt 2 lw 1 pt 2 ps 0.5;
set style line 7 lt 6 lw 1 pt 4 ps 0.5;
set style line 8 lt 8 lw 1 pt 4 ps 0.5;
set style line 20 lt 7 lw 1 pt 4 ps 0.5;
set terminal dumb;
plot "/var/folders/v1/p225k3n12ds2h16xhxv0zjzc0000gn/T/eplot20210502-58630-la1u7e" with lines ls 1
'| gnuplot -persist


  200 +--------------------------------------------------------------------+
      |             +   .+        +            +     +..+    +             |
  180 |-+        +..+..+ :     +                    :   :          +.....+-|
      |:         :       :     ::      +            :   :                  |
  160 |-:   +    :        :    ::      :           :    :       +        +-|
      | : ..:   :         :   :  :    ::          +     :       :          |
      |  +  :   :         :   :  :    : :        +       :      :          |
  140 |-+   :   :         :   :   :  :  :       +        :     :         +-|
      |      :  :         :   :   +  :  :      +         :     :           |
  120 |-+    :  :         :   :    +:   :      :         :     :         +-|
      |      : :           :  :     +   :     :          :     :           |
  100 |-+    : :           : :           :    :          :     :         +-|
      |      : :           : :           :    :          :    :            |
   80 |-+    : :           : :           :   :           :    :          +-|
      |       ::           : :           :   +           :    :            |
      |       :            : :           :  :             :   :            |
   60 |-+     :             :            :  :             :   :          +-|
      |       +             :             ::              :  :             |
   40 |-+                   +             ::              :  :           +-|
      |             +             +       +    +          +..+             |
   20 +--------------------------------------------------------------------+
      0             5             10           15            20            25

横軸を時間にできない。というか横軸をデータの出現順以外にできない。Mbpsは読み取れるようになった。

astkastk

asciigraph をインストールする。インストール対象はプロジェクトの cmd/asciigraph サブディレクトリ。

go install github.com/guptarohit/asciigraph/cmd/asciigraph

早速表示してみる。

asa-taka@tailmoon ~ % cat /var/log/speedtest | jq -r '[.download.bandwidth*8/1000000] | @csv' | asciigraph -h 10 -c 'Download Bandwidth (Mbps)'
 192 ┤      ╭╮        ╭╮        ╭╮
 176 ┼╮  ╭──╯│╭╮      │╰╮   ╭╮  │╰
 159 ┤│╭╮│   │││ ╭╮  ╭╯ │ ╭─╯╰╮ │
 143 ┤╰╯││   │││ ││  │  │ │   │ │
 126 ┤  ││   ││╰╮││ ╭╯  │ │   │ │
 109 ┤  ││   ││ ╰╯│ │   │ │   │ │
  93 ┤  ││   ││   │ │   │ │   │ │
  76 ┤  ││   ││   │ │   │ │   │ │
  60 ┤  ││   ││   │╭╯   │ │   │ │
  43 ┤  ╰╯   ││   ││    │ │   ╰╮│
  27 ┤       ╰╯   ╰╯    ╰─╯    ╰╯
        Download Bandwidth (Mbps)

できた。けど tail -f でリアルタイム描画が行えない。デモだとできそうなんだけど。

astkastk

とりあえず動かしてみる。データは適当。

asa-taka@tailmoon asciigraph % seq 5 | awk '{print 2*$1, $1*$1}' | feedgnuplot --terminal 'dumb' --unset grid


  25 +---------------------------------------------------------------------+
     |        +        +       +        +        +        +       +        |
     |                                                                     |
     |                                                                     |
  20 |-+                                                                 +-|
     |                                                                     |
     |                                                                     |
     |                                                    B                |
  15 |-+                                                                 +-|
     |                                                                     |
     |                                                                     |
     |                                                                     |
  10 |-+                                                                 +-|
     |                                  B                                  |
     |                                                    A                |
     |                                  A                                  |
   5 |-+                                                                 +-|
     |                 B                                                   |
     |                                                                     |
     |        +        +       +        +        +        +       +        |
   0 +---------------------------------------------------------------------+
     1       1.5       2      2.5       3       3.5       4      4.5       5
astkastk

feedgnuplot は eplot よりも多くのオプションを gnuplot にそのまま渡せる。

asa-taka@tailmoon asciigraph % cat /var/log/speedtest | jq -r '[.timestamp, .download.bandwidth*8/1000000] | @csv' | feedgnuplot --line --terminal 'dumb' --set 'datafile separator ","' --unset grid --ymin=0 --ymax=220


      +--------------------------------------------------------------------+
      |         +         +         +        +         +         +         |
  200 |-+                                                                +-|
      |          ******   *              ***         **      ****** **     |
      | *       *     *   *              * *        *  *     *     *       |
      |  *  *   *     *   **    *       *  *     ***   *     *             |
  150 |-+* **   *     *   **    *       *  *     *     *     *           +-|
      |   * *  *       * *  *  **      *    *    *      *   *              |
      |      * *       * *  *  * *    *     *    *      *   *              |
      |      * *       * *   **  *    *     *   *       *   *              |
      |      * *       * *    *  *   *      *   *       *   *              |
  100 |-+    * *       * *       *   *      *   *       *   *            +-|
      |      * *       * *       *   *      *   *       *   *              |
      |       *        * *       *  *       *   *        * *               |
      |       *         *         * *       *   *        * *               |
   50 |-+     *         *         **         * *         * *             +-|
      |                 *         **         * *         ***               |
      |                 *         *          ***                           |
      |                                      *                             |
      |         +         +         +        +         +         +         |
    0 +--------------------------------------------------------------------+
      0         5         10        15       20        25        30        35

あとは横軸を時刻にしたい。

astkastk

feedgnuplotでもasciigraphでもリアルタイム系の処理ができないのはmacのせいなのかな。

astkastk

一応出力はできた。gnuplotで , 区切りのデータを受け取ろうと --set 'detafile separater ","' したけれどうまく動かなかったのでスペース区切りにした。

asa-taka@tailmoon asciigraph % cat /var/log/speedtest | jq -r '[.timestamp, .download.bandwidth*8/1000000] | join(" ")' | feedgnuplot --terminal dumb --unset grid --domain --line --timefmt "%Y-%m-%dT%H:%M:%SZ" --set 'format x "%H:%M"'


  200 +--------------------------------------------------------------------+
      |     +     +*   +     +     +   ***    +   * +     ****  +*   *     |
  180 |-+     ******   *               * *       * *      *   ****   *   +-|
      |*      *    *   *     *        *  *       *  *     *      *   *   * |
  160 |*+ *   *    *   **    *        *  *    ***   *     *      *   *   *-|
      | ***   *    *   **   **       *   *    *     *     *      *   *   * |
      | * *  *      *  **   **      *     *   *     *    *        * * *  * |
  140 |-+ *  *      * *  *  * *     *     *   *      *   *        * * * *+-|
      |    * *      * *  *  * *    *      *  *       *   *        * * * *  |
  120 |-+  * *      * *   **  *    *      *  *       *   *        * * * *+-|
      |    * *      * *    *  *   *       *  *       *   *        * * * *  |
  100 |-+  * *      * *       *   *       *  *       *   *        * * * *+-|
      |    * *      * *       *   *       *  *       *   *        * * * *  |
   80 |-+  * *      * *       *  *        *  *       *   *        * * * *+-|
      |     *        **       *  *        *  *        * *          *   **  |
      |     *        *         * *         * *        * *          *   *   |
   60 |-+   *        *         **          **         * *          *   * +-|
      |     *        *         **          **         ***          *   *   |
   40 |-+            *         *           **           *          *   * +-|
      |     +     +    +     + *   +     + ** +     +     +     +    +     |
   20 +--------------------------------------------------------------------+
    05:30 06:00 06:3007:00 07:30 08:00 08:3009:00 09:30 10:00 10:3011:00 11:30
astkastk

結局欲しい時にすぐに思い出せる方法が一番使いやすいので jq で適当に簡易スパークライン的なものを作るのが良いのではという結論になる。

asa-taka@tailmoon asciigraph % tail -f /var/log/speedtest | jq -r '.bar="=" * (.download.bandwidth*8/1000000/10) | "\(.timestamp) | \(.bar) \(.download.bandwidth*8/1000000)"'
2021-05-02T10:00:27Z | =================== 192.32652
2021-05-02T10:10:22Z | ================== 189.49224
2021-05-02T10:20:23Z | ================== 182.50232
2021-05-02T10:30:22Z | ================= 177.598632
2021-05-02T10:40:24Z | ================== 189.188096
2021-05-02T10:50:34Z | === 37.60528
2021-05-02T11:00:21Z | =================== 190.045992
2021-05-02T11:10:29Z | === 39.5848
2021-05-02T11:20:23Z | ================ 169.244216
2021-05-02T11:30:24Z | ================= 179.323128

jq に固定長で数字を出力する方法があれば嬉しい。
https://github.com/stedolan/jq/issues/614

astkastk

macだと電源を入れている時以外cronが動かなかったので、Raspberry Pi 2をセットアップしてそこで動かすことにした。
https://zenn.dev/asataka/scraps/c25a698ff7cfd8

astkastk

Raspberry Pi 2 のネットワークインタフェースのスペックはこんな感じ。

Settings for eth0:
	Supported ports: [ TP MII ]
	Supported link modes:   10baseT/Half 10baseT/Full
	                        100baseT/Half 100baseT/Full
	Supported pause frame use: Symmetric Receive-only
	Supports auto-negotiation: Yes
	Supported FEC modes: Not reported
	Advertised link modes:  10baseT/Half 10baseT/Full
	                        100baseT/Half 100baseT/Full
	Advertised pause frame use: No
	Advertised auto-negotiation: Yes
	Advertised FEC modes: Not reported
	Link partner advertised link modes:  10baseT/Half 10baseT/Full
	                                     100baseT/Half 100baseT/Full
	Link partner advertised pause frame use: Symmetric Receive-only
	Link partner advertised auto-negotiation: Yes
	Link partner advertised FEC modes: Not reported
	Speed: 100Mb/s
	Duplex: Full
	Port: MII
	PHYAD: 1
	Transceiver: internal
	Auto-negotiation: on
	Supports Wake-on: pumbag
	Wake-on: d
	Current message level: 0x00000007 (7)
			       drv probe link
	Link detected: yes

100baseT なので 100Mbps が最高値になる。契約では200Mbpsまで出るので最高値が頭打ちになってしまうが、100Mbpsを切った時間帯が把握できれば十分な気がするのでひとまずこれで良いものとする。

astkastk

せっかくなのでlogrotateの設定をしてみる。音に効いたプログラムだけれど初めて使う。

astkastk

別にRaspberry Piなので / 以下で実行してもいいのだけれど、ちょっと試しに実行ファイルも設定もログも ~pi 内に置くようにしてみる。

設定ファイルが以下の通りで、/etc にあったものの構成を参考に一部そのまま持ってきた。

pi@pi2a:~ $ tree ~/.config
/home/pi/.config
├── logrotate.conf
├── logrotate.d
│   └── speedtest

pi@pi2a:~ $ cat ~/.config/logrotate.conf
# see "man logrotate" for details
# rotate log files weekly
weekly
# keep 4 weeks worth of backlogs
rotate 4
# create new (empty) log files after rotating old ones
create
# use date as a suffix of the rotated file
#dateext
# uncomment this if you want your log files compressed
#compress
# packages drop log rotation information into this directory
include /home/pi/.config/logrotate.d

# system-specific logs may be also be configured here.
pi@pi2a:~ $ cat ~/.config/logrotate.d/speedtest
~/var/log/speedtest {
        rotate 8
}

include~ を認識してくれなかった。~/var/log/speedtest は認識してくれたんだけど

ログファイルが以下の通り。いい置き場が見つからなかったので /var の構成をそのまま再現。

pi@pi2a:~ $ tree ~/var
/home/pi/var
├── lib
│   └── logrotate
│       └── status.tmp
└── log
    ├── speedtest
    └── speedtest.1

pi@pi2a:~ $ cat ~/var/lib/logrotate/status.tmp
logrotate state -- version 2
"/home/pi/var/log/speedtest" 2021-5-4-23:45:47

speedtest.1は設定の確認のため logrotate -f で出力したもの。 status.tmpのtmpは要らなかったかも。

crontabには以下のように登録する。10分おきに実行する。

pi@pi2a:~ $ crontab -l
*/10 * * * * /home/pi/bin/speedtest -f json >> /home/pi/var/log/speedtest
0 0 * * 0 logrotate -s ~/var/lib/logrotate/status.tmp ~/.config/logrotate.conf
astkastk

ユーザのcronのログ置き場とか設定置き場って $HOME 下にするとしたらどこがいいんだろう。あまりそういうことはしないのかな。