CentOSのISOイメージダウンロードが最も速そうなミラーサイトを調べるスクリプト

# 大きいファイルはスループットが速いサイトからダウンロードしたい
OSのインストール用ISOのように大きめのファイルをダウンロードする場合は、スループットの速いサイトを利用したいものです。ネットワーク上の距離（ホップ数）が少ないならさらにベターです。しかし、自分の居場所からのスループットが速いサーバを調べるのは意外にめんどくさいものです。

そこで、適切なミラーサイトを見つけるためのデータを収集するスクリプトを書いてみました。

# 実行例
スクリプトを実行すると、こういう出力が得られます。

```bash
$ ./centos_mirrorsite_speedtest.sh
mirror.fairway.ne.jp    rtt min/avg/max/mdev = 16.641/17.757/25.294/2.529 ms    5.092 Mbit/s
ftp.iij.ad.jp   rtt min/avg/max/mdev = 3.095/3.426/4.586/0.421 ms       80.299 Mbit/s
ftp.jaist.ac.jp rtt min/avg/max/mdev = 17.870/18.271/19.266/0.515 ms    29.983 Mbit/s
ftp-srv2.kddilabs.jp      78.340 Mbit/s
ftp.nara.wide.ad.jp     rtt min/avg/max/mdev = 9.681/10.608/15.241/1.696 ms     45.502 Mbit/s
ftp.riken.jp    rtt min/avg/max/mdev = 3.966/4.133/4.550/0.170 ms       79.223 Mbit/s
ftp.tsukuba.wide.ad.jp  rtt min/avg/max/mdev = 4.069/4.396/5.642/0.455 ms       71.108 Mbit/s
$
```

この出力は、サイトごとに以下の情報を出力しています。

- ping の実行結果
- curl での速度計測結果

ダウンロードのビットレートは Linux のカーネルイメージである vmlinuz をそれぞれのサイトからダウンロードして計測しています。

上記の例ではビットレートだけを見れば ftp.iij.ad.jp を使うのが最も良さげに見えます。しかし ping の実行結果を見ると ftp.riken.jp のほうが mdev (標準偏差) が小さいのでびっトレードの変動が少ないかもしれません。速度比較となるとビットレートだけを気にしてしまいがちですが、通信経路の安定性も気にするほうが良いと思います。

さらに言えば traceroute でホップ数を取得して比較してみたいのですが、サイトや経路によってはうまく行かないことがあります。なので、確実に比較できる情報としては ping の実行結果とビットレートの２つです。

なお、上記結果の中で kddilabs.jp で ping の結果が表示されないのですが、これはこのサーバがどうやら icmp をフィルタされているためです。



# 実装

動作確認は CentOS7 だけで行っています。ping の出力メッセージの仕様が CentOS7 とは異なる場合は想定通りに動かないかもしれません。ただし curl がインストールされていれば少なくとも速度計測は正しく行えます。

またスクリプト自体は大変シンプルな実装ですので、CentOS以外のミラーサイト比較も容易に行えます。この場合はサイトのURL一覧とTARGETPATHを目的にあわせて修正してください。

```bash:centos_mirrorsite_speedtest.sh
#!/bin/bash

# CentOS のミラーサイトに対する ping の RTT やスループットを測るスクリプト
#
# ・行っていること
#　　ping を10回実効して、RTTの結果だけを抽出する。ave や mdev の値が小さいほうがベターと思われる。
# 　 CentOS7 の isolinux/initrd.img (約40MB) をダウンロードする時間を測る。
#
# ミラーサイトの一覧はここらへんを参照
# https://www.centos.org/download/mirrors/

#TARGETPATH="7/os/x86_64/isolinux/initrd.img"
TARGETPATH="7/os/x86_64/isolinux/vmlinuz"
targetfile=${TARGETPATH##*/}

for mirrorsite in $(
cat << EOL
http://mirror.fairway.ne.jp/centos/
http://ftp.iij.ad.jp/pub/linux/centos/
http://ftp.jaist.ac.jp/pub/Linux/CentOS/
http://www.ftp.ne.jp/Linux/packages/CentOS/
http://ftp.nara.wide.ad.jp/pub/Linux/centos/
http://ftp.riken.jp/Linux/centos/
http://ftp.tsukuba.wide.ad.jp/Linux/centos/
EOL
); do (
       downloadpath=${mirrorsite%/}/${TARGETPATH}
       testpath=${downloadpath%/${targetfile}}

       url_hostname_path=${testpath#http://}
       targethost=${url_hostname_path%%/*}

       # 速度テスト用のファイルがあるかどうか？
       curlresult_test=$( curl --head --silent --output /dev/null --write-out "%{http_code}" ${downloadpath} )

       # ファイルが無いならスキップ
       if [ "$curlresult_test" -ge 400 ]; then
        echo "[abort] cannot find centos mirror path"
        exit
       fi

       # 別のURLにリダイレクトされたら、そのURLからホスト名を取得する
       if [ "$curlresult_test" -ge 300 ]; then
        downloadpath=$( curl --head --silent --output /dev/null --write-out "%{redirect_url}" ${downloadpath} )
        testpath=${downloadpath%/${targetfile}}

        url_hostname_path=${testpath#http://}
        targethost=${url_hostname_path%%/*}
       fi

       # ping で RTT を調べる
       echo -n  "${targethost}"
       pingresult=$( ping ${targethost} -c 10 | tail -1 )
       echo -en "\t${pingresult}"

       # ダウンロード速度を調べる
       curlresult=$( curl --location --silent --output /dev/null --write-out "%{speed_download}\n" ${downloadpath} )
       curlresult=$( echo "scale=3; 8*${curlresult} / (1048576)" |  bc )
       echo -e  "\t${curlresult} Mbit/s"
);
done
```