先日、無線 LAN が標準搭載された Raspberry Pi 3 が発売されましたね。それ以前は USB 無線子機などを利用して Wi-Fi 接続する必要がありました。私の保有する Raspberry Pi は少々古くて B+ モデルです。いろいろな人の記事をみて、どうやら PLANEX 無線LAN子機 GW-USNANO2A が評判がよさそうなので購入して設定してみたところ確かに無線通信できるようになりました (SSID やパスワード設定方法は省略)。
ところが困ったことに ssh 通信していると結構な頻度で通信が切れてしまいます。
原因は主に二種類あるようです。
いろいろと検索すると省電力モードにしないための設定が出てきますが、私の環境ではどれを試してもうまくいきませんでした。Raspberry Pi の OS や無線子機によって有効だったり有効じゃなかったりする対処法ばかりでした。
もっと一般的な対処方法があります。
ssh -o ServerAliveInterval=1 pi@192.168.179.4
-o ServerAliveInterval=1
というオプションを付与するだけです。これは
~/.ssh/config
Host pi
HostName 192.168.179.4
User pi
ServerAliveInterval 1
と ssh 設定ファイルを編集してから
ssh pi
としても同じです。パスワードはご存知のとおり raspberry
ですね。
パケットキャプチャしてみましょう。
sudo tcpdump host 192.168.179.4
PC (192.168.179.3) から Raspberry Pi (192.168.179.4) に一秒ごとにパケットが送信されています。
00:51:55.399364 IP 192.168.179.3.55623 > 192.168.179.4.ssh: Flags [P.], seq 5334:5390, ack 6370, win 4096, options [nop,nop,TS val 399702904 ecr 217335], length 56
00:51:55.404845 IP 192.168.179.4.ssh > 192.168.179.3.55623: Flags [P.], seq 6370:6410, ack 5390, win 815, options [nop,nop,TS val 217436 ecr 399702904], length 40
このため無線 LAN 子機が省電力モードに切り替わることもないですし SSH がタイムアウトすることもありません。通信が途切れるときは以下のようなパケットキャプチャが得られます。
01:22:06.325687 ARP, Request who-has 192.168.179.4 tell 192.168.179.3, length 28
ARP で 192.168.179.4 の MAC アドレスを検索したときに Raspberry Pi が反応してくれていません。
ssh の途中で通信が切れることはなくなりましたが、ssh を閉じているときに USB 無線 LAN 子機が省電力モードに入ってしまうと今度はそもそも ssh できなくなってしまいます。USB 無線 LAN 子機を抜き差しすれば復活しますが、面倒です。かといって、汎用的に省電力モードを無効化できる方法も見当らない。どうしたらいいのか。ping を打ち続けるというのがシンプルでスマートな方法の一つです。
デフォルトゲートウェイに ping を打ちつづける
sudo ping 192.168.179.1
外部の適当なサーバーに ping を打ちつづける (怒られそう)
sudo ping www.example.com
これで bot などを動かしているときに通信ができなくなる事態を回避できますね。Raspberry Pi 起動時にこれが自動で実行され始めるように設定しておくと快適になりそうです。/etc/rc.local
という Windows のスタートアップのようなファイルに以下の一行を exit 0
よりも前に追加してみましょう。sleep 30
は無線 LAN が利用できるようになるまでの待ち時間を適当に調整してください。
sleep 30 && nohup ping www.example.com > /tmp/ping.log 2>&1 &
再起動してから確認してみましょう。
tailf /tmp/ping.log
うまくいっていれば ping が継続実行されています。
64 bytes from 93.184.216.34: icmp_seq=1 ttl=50 time=130 ms
64 bytes from 93.184.216.34: icmp_seq=2 ttl=50 time=129 ms
64 bytes from 93.184.216.34: icmp_seq=3 ttl=50 time=131 ms
64 bytes from 93.184.216.34: icmp_seq=4 ttl=50 time=143 ms
64 bytes from 93.184.216.34: icmp_seq=5 ttl=50 time=146 ms
...