RaspberryPiのTypeAをWi--Fiドングル接続してサーバーとして運用していると思わぬトラブルによってWi-Fiがいつの間にか切断されている。という事態に見舞われることがある。
頻繁に無くても年に一度でもこういう事態に陥ると気が付かないまま数日過ごしてしまうということになりかねない。
以前書いたプログラムで気が付いたら物理的スイッチを用いて安全に電源を入れ直すというのは可能だが、
その場にいない場合を想定してLAN接続が切れたら自動的にシステムを再起動させるというコードを書いてみた。
動作は
- socketで適当なサーバー(ルーター)のアドレスに数分おきに適当なGET要求を出す
- 適当なGET要求なので繋がれば返信でBadRequestが返って来るので接続出来ていると確認できる。
- 繋がらなければ返信が来ない。
- その時たまたま繋がらなかっただけかもしれないので5分おきに接続を試みる。
- 3回返答がなければ切断されたとみなす。
- メモリ領域の他のアプリケーションのログデータを退避させておく。
- システムを再起動させる。
以上をデーモンで動作させておく。
コード内の変数delay_minでチェックする間隔を分単位で指定出来るようにして、5分おきにチェックするようにした。
もし、Wi-Fiドングルやルータが本当に故障で繋がらなくなったとしても5分×3回チェックなので起動後15分は手動で対応出来る時間がある。
15分以内に直にモニタとキーボードを接続してデーモンをストップさせれば良い。
インポートしているfile_mngは以前作ったもの
file_mng.py
targetでアクセスするサーバーを指定(僕の場合はルーター)。
一応どのタイミングで再起動することになったのか解るようにログを残すようにした。
-- rebooterd.py --
#!/usr/bin/python
#coding:utf-8
import sys,os
import subprocess
import time
import socket
import file_mng
target = '192.168.0.1'
port = 80
delay_min = 5
count_dc = 0
logfile = "/var/tmp/rebooterd.log"
def log(logdata):
data = file_mng.get_daytime() + ' ' + logdata + '\n'
file_mng.save_add(logfile,data)
def backup():
file_mng.backup_logs()
def reboot():
log("reboot")
comand = ["sudo", "reboot"]
try:
subprocess.call(comand)
except:
log("subprocessErrer")
def disconected():
global count_dc
count_dc += 1
log("count:" + str(count_dc))
if 2 < count_dc:
backup()
reboot()
def access():
try:
clientsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsock.connect*1
clientsock.sendall('GET /RaspberryPi HTTP/1.1')
clientsock.sendall('\r\n')
clientsock.sendall('\r\n')
rcvmsg = clientsock.recv(1024)
clientsock.close()
except:
rcvmsg = 'err'
return rcvmsg
def loop():
log("start")
global count_dc
while True:
time.sleep(delay_min * 60)
msg = access()
if msg == '' or msg == "err":
#if msg != '':#test
disconected()
else:
count_dc = 0
def fork():
pid = os.fork()
if pid > 0: # parent
f2 = open('/var/run/rebooterd.pid','w')
f2.write(str(pid)+"\n")
f2.close()
sys.exit()
if pid == 0: # child
loop()
if __name__=='__main__':
fork()
今回このコードを作るにあたり、file_mngとlog_mailにコードを追加したのでそちらのブログのコードも更新しておいた。
*1:target,port