DreamerDreamのブログ

夢想家の夢です。〜揚げたてのモヤっとしたものをラフレシアと共に〜

Wi-Fiが繋がらなくなったら自動的にシステムを再起動させる

RaspberryPiのTypeAをWi--Fiドングル接続してサーバーとして運用していると思わぬトラブルによってWi-Fiがいつの間にか切断されている。という事態に見舞われることがある。

頻繁に無くても年に一度でもこういう事態に陥ると気が付かないまま数日過ごしてしまうということになりかねない。

以前書いたプログラムで気が付いたら物理的スイッチを用いて安全に電源を入れ直すというのは可能だが、 

dreamerdream.hateblo.jp

 

 

その場にいない場合を想定してLAN接続が切れたら自動的にシステムを再起動させるというコードを書いてみた。

 

動作は

  1. socketで適当なサーバー(ルーター)のアドレスに数分おきに適当なGET要求を出す
  2. 適当なGET要求なので繋がれば返信でBadRequestが返って来るので接続出来ていると確認できる。
  3. 繋がらなければ返信が来ない。
  4. その時たまたま繋がらなかっただけかもしれないので5分おきに接続を試みる。
  5. 3回返答がなければ切断されたとみなす。
  6. メモリ領域の他のアプリケーションのログデータを退避させておく。
  7. システムを再起動させる。

以上をデーモンで動作させておく。

dreamerdream.hateblo.jp

 

 

コード内の変数delay_minでチェックする間隔を分単位で指定出来るようにして、5分おきにチェックするようにした。

もし、Wi-Fiドングルやルータが本当に故障で繋がらなくなったとしても5分×3回チェックなので起動後15分は手動で対応出来る時間がある。

15分以内に直にモニタとキーボードを接続してデーモンをストップさせれば良い。

 

 インポートしているfile_mngは以前作ったもの

 file_mng.py

dreamerdream.hateblo.jp

 

 

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にコードを追加したのでそちらのブログのコードも更新しておいた。

dreamerdream.hateblo.jp 

*1:target,port

kampa.me