使用Python的Supervisor进行进程监控以及自动启动


Posted in Python onMay 29, 2014

做服务器端开发的同学应该都对进程监控不会陌生,最近恰好要更换 uwsgi 为 gunicorn,而gunicorn又恰好有这么一章讲进程监控,所以多研究了下。

结合之前在腾讯工作的经验,也会讲讲腾讯的服务器监控是怎么做的。同时也会讲下小团队又该怎么敏捷的解决。

下面按照监控的方法依次介绍。

一、按照进程名监控

在腾讯内部所有server都是要打包发布的,而在打包过程中是需要填写要监控的进程名,然后在crontab中定时通过ps查询进程是否存在。

这种方法是比较简单的方法,但是考虑到很多进程会在启动之后改名,以及进程名存在各种特殊字符,多个进程同时存在的问题,实际操作起来并不是很舒服。

举个简单的例子,gunicorn启动之后的进程名类似这样 master: [wsgi:app],其中的方括号在grep时要记得转义,否则就会出问题。

不过不管怎么说,这种方法在很多其他方式用不了的时候反而是最简单的方法。

下面是用python的实现:

def monitor_process(key_word, cmd):
    p1 = subprocess.Popen(['ps', '-ef'], stdout=subprocess.PIPE)
    p2 = subprocess.Popen(['grep', key_word], stdin=p1.stdout, stdout=subprocess.PIPE)
    p3 = subprocess.Popen(['grep', '-v', 'grep'], stdin=p2.stdout, stdout=subprocess.PIPE)
    lines = p3.stdout.readlines()
    if len(lines) > 0:
        return
    sys.stderr.write('process[%s] is lost, run [%s]\n' % (key_word, cmd))
    subprocess.call(cmd, shell=True)

二、按照端口监控

这种方式之前在腾讯打包的时候也有用,但是可能是进程名更直观的原因吧,貌似一直没怎么用起来。

不过现在自己在做包部署的时候,反而觉得端口监控是个最靠谱的事情了。这个也没什么好多说的,直接上刚写完的python代码:

def monitor_port(protocol, port, cmd):
    address = ('127.0.0.1', port)
    socket_type = socket.SOCK_STREAM if protocol == 'tcp' else socket.SOCK_DGRAM
    client = socket.socket(socket.AF_INET, socket_type)
    try:
        client.bind(address)
    except Exception, e:
        pass
    else:
        sys.stderr.write('port[%s-%s] is lost, run [%s]\n' % (protocol, port, cmd))
        subprocess.call(cmd, shell=True)
    finally:
        client.close()

有的朋友可能说对于tcp端口检查,其实以client的方式来connect()看是否成功会不会更好?其实我觉得这种方式也挺好的,并且对于不同的协议可以再深入处理一下,比如对http协议可以用urllib2.urlopen确保返回正确的包才算正常。不过如果这么做的话,就有点偏黑盒监控 了,比如监控宝、阿里云监控之类的服务了。

三、通过监控server启动进程,并以监控子进程的方式监控

这个也是在gunicorn页面上看到的,说起来gunicorn很不厚道的把gaffer放到第一个,让我还以为是个很成熟的产品,结果发现连启动都是个问题。

相反排在后面的supervisor反而相当的好用,下面是截图:

使用Python的Supervisor进行进程监控以及自动启动

supervisor可以很方便的管理进程,包括重启,停止等等,而且提供了web界面和用户验证,可以很方便的在线管理。

但是有好处就有坏处,用了supervisor之后,就不能自己随便的去自己重启服务了,否则会影响supervisor的监控,这对我这种喜欢自己执行 xx.sh restart 的人实在有点太痛苦了。当然,其实要是习惯了去supervisorctl 里面start/stop/reload 之后也就还好了。

用supervisor配置gunicorn的配置项如下:

[program:yuanzhaopin]
environment=PYTHON_EGG_CACHE=/tmp/.python-eggs/,PYTHONPATH=/data/release/yuanzhaopin
command=/usr/local/bin/gunicorn --debug --log-level debug --log-file /tmp/g.log wsgi:app
user=zny2008
autorestart=true
redirect_stderr=true

ok,目前自己常用的就是这几种模式了,大家如果有其他选择欢迎留言讨论。

完整代码如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#*/1 * * * * python /xxx/monitor.py >> /xxx/logs/monitor.log 2>&1  &
import sys
import subprocess
import os.path as op
import socket
def this_abs_path(script_name):
    return op.abspath(op.join(op.dirname(__file__), script_name))

def monitor_process(key_word, cmd):
    p1 = subprocess.Popen(['ps', '-ef'], stdout=subprocess.PIPE)
    p2 = subprocess.Popen(['grep', key_word], stdin=p1.stdout, stdout=subprocess.PIPE)
    p3 = subprocess.Popen(['grep', '-v', 'grep'], stdin=p2.stdout, stdout=subprocess.PIPE)
    lines = p3.stdout.readlines()
    if len(lines) > 0:
        return
    sys.stderr.write('process[%s] is lost, run [%s]\n' % (key_word, cmd))
    subprocess.call(cmd, shell=True)

def monitor_port(protocol, port, cmd):
    address = ('127.0.0.1', port)
    socket_type = socket.SOCK_STREAM if protocol == 'tcp' else socket.SOCK_DGRAM
    client = socket.socket(socket.AF_INET, socket_type)
    try:
        client.bind(address)
    except Exception, e:
        pass
    else:
        sys.stderr.write('port[%s-%s] is lost, run [%s]\n' % (protocol, port, cmd))
        subprocess.call(cmd, shell=True)
    finally:
        client.close()

#=============================================================================
def yuanzhaopin():
    cmd = '%s start' % this_abs_path('gun.sh')
    #monitor_process('\[yuanzhaopin\]', cmd)
    monitor_port('tcp', 8635, cmd)

def main():
    yuanzhaopin()

if __name__ == '__main__':
    main()
Python 相关文章推荐
详解Python中break语句的用法
May 14 Python
Python3.6连接Oracle数据库的方法详解
May 18 Python
解决Shell执行python文件,传参空格引起的问题
Oct 30 Python
利用Python对文件夹下图片数据进行批量改名的代码实例
Feb 21 Python
python时间序列按频率生成日期的方法
May 14 Python
Python识别快递条形码及Tesseract-OCR使用详解
Jul 15 Python
Python编程中类与类的关系详解
Aug 08 Python
画pytorch模型图,以及参数计算的方法
Aug 17 Python
python ubplot使用方法解析
Jan 10 Python
Python 基于FIR实现Hilbert滤波器求信号包络详解
Feb 26 Python
pytorch显存一直变大的解决方案
Apr 08 Python
python字符串常规操作大全
May 02 Python
python应用程序在windows下不出现cmd窗口的办法
May 29 #Python
python正则表达式re模块详细介绍
May 29 #Python
在python中的socket模块使用代理实例
May 29 #Python
python中stdout输出不缓存的设置方法
May 29 #Python
python两种遍历字典(dict)的方法比较
May 29 #Python
python中常用的各种数据库操作模块和连接实例
May 29 #Python
从零学Python之入门(五)缩进和选择
May 27 #Python
You might like
通过缓存数据库结果提高PHP性能的原理介绍
2012/09/05 PHP
php实现的SSO单点登录系统接入功能示例分析
2016/10/12 PHP
PHP实现本地图片转base64格式并上传
2020/05/29 PHP
Web前端设计模式  制作漂亮的弹出层
2010/10/29 Javascript
删除select中所有option选项jquery代码
2013/08/12 Javascript
jquery+easeing实现仿flash的载入动画
2015/03/10 Javascript
简单分析javascript面向对象与原型
2015/05/21 Javascript
JS实现淡蓝色简洁竖向Tab点击切换效果
2015/10/06 Javascript
原生js实现瀑布流布局
2017/03/08 Javascript
关于javascript作用域的常见面试题分享
2017/06/18 Javascript
vue下跨域设置的相关介绍
2017/08/26 Javascript
Webpack的dll功能使用
2018/06/28 Javascript
js实现每日签到功能
2018/11/29 Javascript
JavaScript实现身份证验证代码实例
2019/08/26 Javascript
js实现贪吃蛇游戏 canvas绘制地图
2020/09/09 Javascript
Vuex实现简单购物车
2021/01/10 Vue.js
[43:51]2018DOTA2亚洲邀请赛3月30日 小组赛B组 EG VS Secret
2018/03/31 DOTA
Django的session中对于用户验证的支持
2015/07/23 Python
python实现域名系统(DNS)正向查询的方法
2016/04/19 Python
解决pyqt中ui编译成窗体.py中文乱码的问题
2016/12/23 Python
10个Python小技巧你值得拥有
2018/09/29 Python
python random从集合中随机选择元素的方法
2019/01/23 Python
详解用pyecharts Geo实现动态数据热力图城市找不到问题解决
2019/06/26 Python
pandas删除行删除列增加行增加列的实现
2019/07/06 Python
python中matplotlib条件背景颜色的实现
2019/09/02 Python
Python高阶函数、常用内置函数用法实例分析
2019/12/26 Python
python Popen 获取输出,等待运行完成示例
2019/12/30 Python
Jupyter notebook无法导入第三方模块的解决方式
2020/04/15 Python
python函数中将变量名转换成字符串实例
2020/05/11 Python
Opencv常见图像格式Data Type及代码实例
2020/11/02 Python
CSS3的transition和animation的用法实例介绍
2014/08/20 HTML / CSS
Pam & Gela官网:美国性感前卫女装品牌
2018/07/19 全球购物
C++:局部变量能否和全局变量重名
2014/03/03 面试题
2014年客服工作总结范文
2014/11/13 职场文书
恋恋笔记本观后感
2015/06/16 职场文书
2016年教代会开幕词
2016/03/04 职场文书