简易注册中心监控NAS断电断网

132 阅读2分钟

日常使用NAS过程中,偶尔会出现家里断电或者断网的情况,NAS自带网络断开的通知功能,但需要是恢复网络链接后才会通知,而此时都恢复了,再通知也就没那么重要,还有断电情况下也是需要回家才能知道,断电保护可以使用UPS,当停电后UPS通过usb数据线会给NAS发送通知,NAS收到通知后在设定时间内关机并发送ups进入电池供电模式的通知,但这个方式需要购买ups设备,成本在300元左右。

注册中心原理

联想到注册中心等其他集群模式下的心跳连接,心跳超时则进行剔除的方式,自己便用python写了一个简单的web服务当作注册中心,再写一个定时任务每隔5秒扫描一遍最近注册时间数据,对比下来如果超时60秒以上,则认为NAS已经失去链接,立刻发送邮件/钉钉通知,当NAS重新上线连接后,定时任务扫描到注册信息会再发送已经连接的通知信息。

NAS端原理

上文已经通过python提供了一个web服务,此时只需要在NAS端任务计划中创建一个每分钟的定时任务即可,定时请求心跳接口,服务端记录请求时间。

或者在docker里启动一个定时任务,crontab命令

service cron start
*/1 * * * * curl http://ip:2580/register                            

服务端代码

启动python的命令,需要在后台运行

ps -ef|grep python
nohup python3 nas_health.py  &
nohup python3 nas_register.py  &

nas_register-类似于注册中心的概念,提供一个get接口供NAS访问

# -*- encoding: utf-8 -*-
import os
import datetime
import tornado.web


class MainHandler(tornado.web.RequestHandler):
    def get(self):
        """get请求"""
        now = datetime.datetime.now()
        out = open("nas_datetime-" + str(now.year) + '-' + str(now.month) + '-' + str(now.day), 'a')
        out.write(str(now) + '\n')
        out.close()
        self.write("")


application = tornado.web.Application([(r"/register", MainHandler)],
                                      static_path=os.path.join(os.path.dirname(__file__), "static"), )


# 读取文件中的数据
def read_txt_file(file_name):
    newFile = open(file_name)
    data = newFile.read()
    newFile.close()
    return data


if __name__ == "__main__":
    application.listen(2580)
    tornado.ioloop.IOLoop.instance().start()

nas_health-定时扫描日志文件,对比注册时间

# -*- encoding: utf-8 -*-
import datetime
import time
import smtplib
from email.mime.text import MIMEText
from email.header import Header


# 读取文件中的数据
def read_txt_file(file_name):
    newFile = open(file_name)
    data = newFile.read()
    if data == '':
        return ''
    now = ''
    for line in data.split('\n'):
        if line == '':
            break
        now = line
    newFile.close()
    return now


def loop_monitor():
    email_state = True
    while True:
        try:
            file_now = datetime.datetime.now()
            now_str = read_txt_file(
                "nas_datetime-" + str(file_now.year) + '-' + str(file_now.month) + '-' + str(file_now.day))
            if now_str == '':
                continue
            now = datetime.datetime.strptime(str(now_str), "%Y-%m-%d %H:%M:%S.%f")
            now2 = datetime.datetime.now()
            print((now2 - now).seconds)
            if (now2 - now).seconds >= 60 and email_state:
                email("心跳已经超时", "xxx@xxx.com")
                email_state = False
            if (now2 - now).seconds < 60 and email_state == False:
                email_state = True
                email("心跳已经恢复", "xxx@xxx.com")
        except Exception as e:
            print("时间错误", e)
        time.sleep(5)  # 暂停5秒


def email(text, toemail):
    sender = "xxx@xxx.com"  # 发送方的邮箱
    password = "xxxx."  # 邮箱的授权码
    receiver = toemail  # 接收方的邮箱
    data_time = time.strftime("%Y-%m-%d %H:%M:%S")
    subject = data_time + "Nas服务器心跳报警"  # title邮件标题
    words = text  # text邮件内容
    msg = MIMEText(words, 'plain', 'utf-8')  # 中文需参数‘utf-8',单字节字符不需要
    msg['Subject'] = Header(subject, 'utf-8')  # 邮件标题
    msg['from'] = sender  # 发信人地址
    msg['to'] = receiver  # 收信人地址
    smtp = smtplib.SMTP_SSL("smtp.exmail.qq.com", 465)
    smtp.connect('smtp.exmail.qq.com')
    smtp.login(sender, password)
    smtp.sendmail(sender, receiver, msg.as_string())
    smtp.quit()


if __name__ == "__main__":
    loop_monitor()