Akiyagriにおけるカメラサーバ
リモートの空き家で育てている野菜の成長度合いを確認するために、リクエストに応じて写真を撮ってレスポンスするサーバ。
別のところに用意したサーバ(public IPが割り振られている)にsshトンネルをはり、サーバにあるスラックのbotサーバが逆sshを通じて写真をリクエストする。
ちなみに、このカメラサーバはUbuntu 16.04 Serverである。
sshトンネルを張る
ssh_tunnel() {
while :
do
ssh -i $RSA_SECRET_KEY -R 4050:localhost:4050 $1 -N -o ServerAliveInterval=20 -o ServerAliveCountMax=3 >> $2 2>&1
done
}
ssh_tunnel $PROXY_SERVER_USER@$PROXY_SERVER_HOST $SSH_LOG_FILE &
上記のスクリプトによって、botサーバがlocalhost:4050にリクエストを送ると、空き家においてあるサーバのlocalhost:4050につながるようになる。
以前は、sshトンネルを張ってからしばらく放置すると接続が勝手に死んでしまい、sshのプロセス自体は残っているが、逆ssh出来なく成るということが起こっていた。
ServerAliveCountMaxとServerAliveIntervalオプションをしっかり指定することで、一定期間放置するとタイムアウトして、sshのプロセスを一旦killして、再接続するように下のが上記のスクリプトである。
一晩置いたらトンネルが使えなくなる
実際に運用する前に、1ヶ月程度自宅でカメラサーバを走らせた。このときはsshトンネルが死ぬことはなかった。
systemctlに登録してあるので、sshトンネルは起動時に自動的に張られる。そこで、何度か再起動チェックも行っており、それも上手く行っていた。
しかし、いざ野菜を育てている空き家(銚子の方)に持っていったら、一晩でsshトンネルが使えなくなった。
ps aux | grep sshd
をbotが動いているサーバで実行してみると、sshトンネルを受け付けているプロセスがない。
考えられる原因
- b-mobileのSIMカードが入ったWi-Fiルータが死んでいる(容量いっぱい)
- パソコンが電源にちゃんとつながっていいない
- スリープモードが発動した
- sshコマンドが何らかのエラーを吐き続けている。
1のルータが死んでいる説は、他のセンサデータのダウンロードが出来ているので可能性が低い(1ヶ月間の事前テスト環境と唯一違う部分なので一番あやしいと思ったのだが、、、)。
3のスリープモードは、 sudo systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target
で無効にしているし、事前のチェックでも勝手にスリープモードになって繋がらなくなることはなかった。
2の電源につながっていない説に関しては、近くにあった電源タップに挿した記憶はある。しかし、そのタップが実はプラグインされていなかった可能性がある。
4については、Wi-Fiが不安定になったとあいまって生じた可能性を否定できない。せめて、リモートから再起動できれば。。。
引き続き原因究明。。。制御系は難しい。。。こういうの慣れている方がいれば
Chromeのリモートデスクトップとかって、どうやってここらへん保障しているのだろうか?
リモートホストから定期的にサーバにアクセスして、サーバが特定のステートを返したら指定のスクリプト(再起動スクリプトなど)を実行する仕組みをつくるといいかもしれない。
カメラサーバの状態
後日現地に赴いて様子みた。
root 1076 0.0 0.0 4504 932 ? S 14:22 0:00 /bin/sh /usr/local/bin/reverse_ssh.sh
root 1077 0.0 0.0 4504 916 ? S 14:22 0:00 /bin/sh /usr/local/bin/reverse_ssh.sh
root 3856 0.0 0.1 65508 5356 ? Ss 14:22 0:00 /usr/sbin/sshd -D
root 5764 0.0 0.1 46984 5268 ? S 14:31 0:00 ssh -i /home/matthew/.ssh/akiya_server -R 4040:localhost:22 ishige@akiyagri.akg.t.u-tokyo.ac.jp -N -o ServerAliveInterval=20 -o ServerAliveInterval=3
root 5776 0.0 0.1 46984 5300 ? S 14:31 0:00 ssh -i /home/matthew/.ssh/akiya_server -R 4050:localhost:4050 ishige@akiyagri.akg.t.u-tokyo.ac.jp -N -o ServerAliveInterval=20 -o ServerAliveCountMax=3
root 5779 0.0 0.1 46984 5380 ? S 14:31 0:00 ssh -i /home/matthew/.ssh/akiya_server -R 4041:localhost:22 ishige@akiyagri.akg.t.u-tokyo.ac.jp -N -o ServerAliveInterval=20 -o ServerAliveInterval=3
matthew 5829 0.0 0.1 46988 5424 tty1 R+ 15:10 0:00 ssh -i .ssh/akiya_server -R 4444:localhost:22 -N ishige@akiyagri.akg.t.u-tokyo.ac.jp
root 5830 0.0 0.1 111300 7632 ? Ss 15:10 0:00 sshd: matthew [priv]
matthew 5861 0.0 0.0 111300 3568 ? S 15:10 0:00 sshd: matthew@pts/0
matthew 5878 0.0 0.0 12944 964 pts/0 S+ 15:11 0:00 grep --color=auto ssh
sshのプロセスは生きているのにも関わらず、トンネルは使えていない模様。ちなみに、カメラサーバは電源が落ちていたようである。
systemctl status suspend.target
suspend.target - Suspend
Loaded: loaded (/lib/systemd/system/suspend.target; static; vendor preset: enabled)
Active: inactive (dead)
Docs: man:systemd.special(7)
だったので、一応もう一度マスクをかける。念のため電源も確認する。
cat /sys/class/power_supply/AC/online
> 1
ちゃんとACアダプタのつながっている模様。
sshが吐き出しているログを見ると
...
Warning: Identity file /home/***/.ssh/akiya_server not accessible: No such file or directory.
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
というログをひたすら吐き続けていた。sshトンネルを作るスクリプトは/usr/local/bin/にありrootで実行するので、一般ユーザ下に存在する秘密鍵を使うはまずいのかもしれない。そこで、秘密鍵を/usr/local/にコピーして、そこに置いた秘密鍵を使うように変更した。