Python 自启动&监听进程 服务

来源:互联网 发布:淘宝网店图标尺寸 编辑:程序博客网 时间:2024/06/01 23:29

目标:

最近用python bottle写了一些api,但是阿里的服务器有时候会自动重启,导致api挂掉,所以有了写一个自启动服务的打算。

想法:

因为以前写的自启动和保护服务都是用C++写的服务,由于换了公司,电脑上也没有了vs,懒得装,查了下资料,发现python也能写成服务,就打算用python实现。

正题:

一:python实现服务

需要安装pywin32,因为我用的是python2.7,就下了pywin32-218.win-amd64-py2.7.exe,下载安装请百度。以下是服务整体的代码:class PythonService(win32serviceutil.ServiceFramework):    _svc_name_ = "PythonAutoRunServer"    _svc_display_name_ = "PythonAutoRunServer"    _svc_description_ = "用于Python服务的自启动和监测"    _svc_description_ = _svc_description_.decode('utf8').encode('gbk')    def __init__(self, args):        win32serviceutil.ServiceFramework.__init__(self, args)        self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)        self.logger = self._getLogger()        self.run = True    def _getLogger(self):        logger = logging.getLogger('[PythonService]')        this_file = inspect.getfile(inspect.currentframe())        dirpath = os.path.abspath(os.path.dirname(this_file))        handler = logging.FileHandler(os.path.join(dirpath, "service.log"))        formatter = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s')        handler.setFormatter(formatter)        logger.addHandler(handler)        logger.setLevel(logging.INFO)        return logger    def SvcDoRun(self):        import time        # server_type: 1 后台管理系统; 2 东篱服务        server_name = ["", "后台管理系统", "东篱"]        server_type = 1        self.logger.info("service is run....")        start_server_time = 0   # 连续自启动三次时发邮件警报        while self.run:            try:                if python_run_manage.start_check(server_type) == 1:                    start_server_time += 1                else:                    start_server_time = 0                if start_server_time == 3:                    # 发送邮件警报                    send_mail.send_auth_mail().send_mail_action("服务器警报", server_name[server_type],                                                                "服务器服务重启次数异常")                time.sleep(60)            except Exception, e:                self.logger.info(str(e))                self.logger.info("sssss")                time.sleep(60)        self.logger.info("----------  svcdorun end  --------------")    def SvcStop(self):        self.logger.info("service is stop....")        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)        self.run = Falseif __name__ == '__main__':    win32serviceutil.HandleCommandLine(PythonService)

这个服务是我百度找到的,其中send_mail是我的邮件通知模块,python_run_manage是具体监听进程是否正在运行的模块。

服务的安装等命令

1. 在环境中安装 pywin32-218.win-amd64-py2.72. 管理员启动的cmd中安装 python PythonAutoRunServer.py  --startup auto install 3. 启动服务 python PythonAutoRunServer.py start

ps:
1. 关闭服务: python PythonAutoRunServer.py stop
2. 删除服务: python PythonAutoRunServer.py remove

二. 监听进程模块

先贴下完整的代码:
# 目标是 监测需要持续运行的Python程序,当没有运行时,自动启动
import httplib
import json

import subprocess    #可用于检测程序是否正常,通过端口能否连接判断    # def check_aliveness(ip, port, process_name):    #     sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)    #     sk.settimeout(1)    #     try:    #         sk.connect((ip, port))    #         print '%s %s %d service is OK!' % (process_name, ip, port)    #         aliveness = True    #     except Exception:    #         print '%s %s %d service is NOT OK!' % (process_name, ip, port)    #         # 自启动    #         _start_py(_get_py_path(process_name))    #         aliveness = False    #     finally:    #         sk.close()    #     return alivenessimport timeimport loggerdef check_aliveness(ip_port, process_name):    need_start = 0    headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"}    conn = httplib.HTTPConnection(ip_port)    try:        conn.request("POST", "/test_connection", json.dumps({}), headers=headers)        response = conn.getresponse()        data = response.read()    except Exception, e:        pass        aliveness = False    try:        json_data = json.loads(data)        error_code = int(json_data["error"])        if error_code == 200:            aliveness = True    except Exception, e:        aliveness = False        print e    if not aliveness:        # 自启动        need_start = 1        _write_log(process_name + " is not ok")        _start_py(_get_py_path(process_name))    else:        _write_log(process_name + " is ok")    return need_start# 存储需要监控的py路径def _get_py_path(process_name):    if process_name == "back_manage":        return r"D:/PythonServer/back_manager/route_for_back_manager.py"    elif process_name == "dongli":        return r"D:/web/python/route_dongli.py"    elif process_name == "dongli_achievement":        return r"D:/web/python/achievement_server.py"# 启动py程序def _start_py(path):    try:        cmd = "python %s" % path        cwd = path[0:path.rindex("/")]        subprocess.Popen(cmd,                         creationflags=subprocess.CREATE_NEW_CONSOLE,                         cwd=cwd)    except Exception, e:        print edef _write_log(content):    logger.Logger(logger="auto_server", message=content)# 开始检测def start_check(check_type):    if check_type == 1:        # 后台管理系统        return check_aliveness('127.0.0.1:4002', "back_manage")    elif check_type == 2:        # 东篱        need_start_one = check_aliveness('127.0.0.1:4000', "dongli")        need_start_two = check_aliveness('127.0.0.1:4001', "dongli_achievement")        if need_start_one == 0 and need_start_two == 0:            return 0        else:            return 1

由服务循环调用start_check,来监测进程。本来是打算用socket来判断服务能否telnet来判断服务是否正常,后来尝试时发现,bottle写的api不能socket,一开始会显示正常,但是你不断开socket就会导致api阻塞,那个时候就会无法ping通…恩,然后就会重启n多的进程,惨惨惨,当然也是我没有把进程写成单例的原因。所以,我在进程中多加了一个test_connection 的api,用来判断进程是否正常。
在_get_py_path方法中保存了进程可执行程序的路径,恩,其实我觉得应该把这些写到cfg文件里会好些,嘛,以后再说~
_start_py方法是用cmd启动python api的方法,CREATE_NEW_CONSOLE这个属性是新开启界面,不过因为是服务启动的进程,所以不会有界面显示~

结束语:

这个服务还是非常简陋的,不过因为现在功能需求不多,还能勉强凑合,以后会加一些自己需要的功能,比如连续重启三次就发邮件给负责人等功能。
原创粉丝点击