写一个python的服务监控程序

前言:

Redhat下安装Python2.7

rhel6.4自带的是2.6, 发现有的机器是python2.4。 到python网站下载源代码,解压到Redhat上,然后运行下面的命令:

# ./configure --prefix=/usr/local/python27

# make

# make install

这样安装之后默认不会启用Python2.7,需要使用/usr/local/python27/bin/python2.7调用新版本的python。

而下面的安装方式会直接接管现有的python

# ./configure

# make

# make install

开始:

服务子进程被监控主进程创建并监控,当子进程异常关闭,主进程可以再次启动之。使用了python的subprocess模块。就这个简单的代码,居然互联网上没有现成可用的例子。没办法,我写好了贡献出来吧。

首先是主进程代码:service_mgr.py

#!/usr/bin/python
#-*- coding: UTF-8 -*-
# cheungmine
# stdin、stdout和stderr分别表示子程序的标准输入、标准输出和标准错误。
#
# 可选的值有:
#   subprocess.PIPE - 表示需要创建一个新的管道.
#   一个有效的文件描述符(其实是个正整数)
#   一个文件对象
#   None - 不会做任何重定向工作,子进程的文件描述符会继承父进程的.
#
# stderr的值还可以是STDOUT, 表示子进程的标准错误也输出到标准输出.
#
# subprocess.PIPE
# 一个可以被用于Popen的stdin、stdout和stderr 3个参数的特输值,表示需要创建一个新的管道.
#
# subprocess.STDOUT
# 一个可以被用于Popen的stderr参数的特输值,表示子程序的标准错误汇合到标准输出.
################################################################################
import os
import sys
import getopt

import time
import datetime

import codecs

import optparse
import ConfigParser

import signal
import subprocess
import select

# logging
# require python2.6.6 and later
import logging
from logging.handlers import RotatingFileHandler

## log settings: SHOULD BE CONFIGURED BY config
LOG_PATH_FILE = "./my_service_mgr.log"
LOG_MODE = 'a'
LOG_MAX_SIZE = 4*1024*1024 # 4M per file
LOG_MAX_FILES = 4          # 4 Files: my_service_mgr.log.1, printmy_service_mgrlog.2, ...
LOG_LEVEL = logging.DEBUG  

LOG_FORMAT = "%(asctime)s %(levelname)-10s[%(filename)s:%(lineno)d(%(funcName)s)] %(message)s"  

handler = RotatingFileHandler(LOG_PATH_FILE, LOG_MODE, LOG_MAX_SIZE, LOG_MAX_FILES)
formatter = logging.Formatter(LOG_FORMAT)
handler.setFormatter(formatter)

Logger = logging.getLogger()
Logger.setLevel(LOG_LEVEL)
Logger.addHandler(handler) 

# color output
#
pid = os.getpid() 

def print_error(s):
    print '\033[31m[%d: ERROR] %s\033[31;m' % (pid, s)

def print_info(s):
    print '\033[32m[%d: INFO] %s\033[32;m' % (pid, s)

def print_warning(s):
    print '\033[33m[%d: WARNING] %s\033[33;m' % (pid, s)

def start_child_proc(command, merged):
    try:
        if command is None:
            raise OSError, "Invalid command"

        child = None

        if merged is True:
            # merge stdout and stderr
            child = subprocess.Popen(command,
                stderr=subprocess.STDOUT, # 表示子进程的标准错误也输出到标准输出
                stdout=subprocess.PIPE    # 表示需要创建一个新的管道
            )
        else:
            # DO NOT merge stdout and stderr
            child = subprocess.Popen(command,
                stderr=subprocess.PIPE,
                stdout=subprocess.PIPE)

        return child

    except subprocess.CalledProcessError:
        pass # handle errors in the called executable
    except OSError:
        pass # executable not found

    raise OSError, "Failed to run command!"

def run_forever(command):
    print_info("start child process with command: " + ' '.join(command))
    Logger.info("start child process with command: " + ' '.join(command))

    merged = False
    child = start_child_proc(command, merged)

    line = ''
    errln = ''

    failover = 0

    while True:
        while child.poll() != None:
            failover = failover + 1
            print_warning("child process shutdown with return code: " + str(child.returncode))
            Logger.critical("child process shutdown with return code: " + str(child.returncode))

            print_warning("restart child process again, times=%d" % failover)
            Logger.info("restart child process again, times=%d" % failover)
            child = start_child_proc(command, merged)

        # read child process stdout and log it
        ch = child.stdout.read(1)
        if ch != '' and ch != '\n':
            line += ch
        if ch == '\n':
            print_info(line)
            line = ''

        if merged is not True:
            # read child process stderr and log it
            ch = child.stderr.read(1)
            if ch != '' and ch != '\n':
                errln += ch
            if ch == '\n':
                Logger.info(errln)
                print_error(errln)
                errln = ''

    Logger.exception("!!!should never run to this!!!")  

if __name__ == "__main__":
    run_forever(["python", "./testpipe.py"])

然后是子进程代码:testpipe.py

#!/usr/bin/python
#-*- coding: UTF-8 -*-
# cheungmine
# 模拟一个woker进程,10秒挂掉
import os
import sys

import time
import random

cnt = 10

while cnt >= 0:
    time.sleep(0.5)
    sys.stdout.write("OUT: %s\n" % str(random.randint(1, 100000)))
    sys.stdout.flush()

    time.sleep(0.5)
    sys.stderr.write("ERR: %s\n" % str(random.randint(1, 100000)))
    sys.stderr.flush()

    #print str(cnt)
    #sys.stdout.flush()
    cnt = cnt - 1

sys.exit(-1)

Linux上运行很简单:

$ python service_mgr.py

Windows上以后台进程运行:

> start pythonw service_mgr.py

代码中需要修改:

run_forever(["python", "testpipe.py"])

写一个python的服务监控程序的更多相关文章

  1. tensorflow学习笔记3:写一个mnist rpc服务

    本篇做一个没有实用价值的mnist rpc服务,重点记录我在调试整合tensorflow和opencv时遇到的问题: 准备模型 mnist的基础模型结构就使用tensorflow tutorial给的 ...

  2. 如何手动写一个Python脚本自动爬取Bilibili小视频

    如何手动写一个Python脚本自动爬取Bilibili小视频 国庆结束之余,某个不务正业的码农不好好干活,在B站瞎逛着,毕竟国庆嘛,还让不让人休息了诶-- 我身边的很多小伙伴们在朋友圈里面晒着出去游玩 ...

  3. 写一个Python的windows服务

    1. 安装pywin32和pyinstaller pip install pywin32 pip install pyinstaller 2.写一个服务Demo # -*- coding: utf-8 ...

  4. 写一个python脚本监控在linux中的进程

    在虚拟机中安装Linux中的CentOS7系统 https://baijiahao.baidu.com/s?id=1597320700700593557&wfr=spider&for= ...

  5. 写一个Python 1、通过select实现的最简单的web框架2、通过wsgiref实现的web框架

    #!/usr/bin/env python # -*- coding: utf- -*- import socket import select class MyRequest: "&quo ...

  6. 写一个python 爬虫爬取百度电影并存入mysql中

    目标是利用python爬取百度搜索的电影 在类型 地区 年代各个标签下 电影的名字 评分 和图片连接 以及 电影连接 首先我们先在mysql中建表 create table liubo4( id in ...

  7. 如何写一个Python万能装饰器,既可以装饰有参数的方法,也可以装饰无参数方法,或者有无返回值都可以装饰

    Python中的装饰器,可以有参数,可以有返回值,那么如何能让这个装饰器既可以装饰没有参数没有返回值的方法,又可以装饰有返回值或者有参数的方法呢?有一种万能装饰器,代码如下: def decorate ...

  8. 写一个python小程序

    在windows环境下进行操作 window+R 输入cmd  创建一个文件夹 mkdir pytxt 创建一个py文件 py.py  用notepad或者记事本等工具进行编辑 或 首先声明pytho ...

  9. 手写一个python迭代器

    分析 我们都知道一个可迭代对象可以通过iter()可以返回一个迭代器. 如果想要一个对象称为可迭代对象,即可以使用for,那么必须实现__iter __()方法. 在一个类的实例对象想要变成迭代器,就 ...

随机推荐

  1. Linux动态频率调节系统CPUFreq之二:核心(core)架构与API

    上一节中,我们大致地讲解了一下CPUFreq在用户空间的sysfs接口和它的几个重要的数据结构,同时也提到,CPUFreq子系统把一些公共的代码逻辑组织在一起,构成了CPUFreq的核心部分,这些公共 ...

  2. Android必知必会-带列表的地图POI周边搜索

    如果移动端访问不佳,请尝试–> Github版 2016-08-22 更新 注意:在 Activity 代码中的onPoiSearched(PoiResult result, int rCode ...

  3. android git上开源的项目收藏

    本文为那些不错的Android开源项目第一篇--个性化控件(View)篇,主要介绍Android上那些不错个性化的View,包括ListView.ActionBar.Menu.ViewPager.Ga ...

  4. ROS(indigo)ABB机器人MoveIt例子

    ROS(indigo)ABB机器人例子 参考网址: 1  http://wiki.ros.org/Industrial 2  http://wiki.ros.org/abb 3  https://gi ...

  5. (一〇六)iPad开发之UIPopoverController的使用

    很多App里都有一种点击显示的悬浮气泡菜单,例如下图: 在iPad上可以使用UIPopoverController实现这个功能,popoverController继承自NSObject而不是UIVie ...

  6. 卸载linux后出现grub rescue怎么办?

    原文转自:http://zhidao.baidu.com/link?url=9e2mOttgV0IJDMml58SFbV-7XOvVzp2jR5l1n3ltFOzX1XAcp5-t-QQPc-Nozy ...

  7. 并发编程之ThreadLocal、Volatile、synchronized、Atomic关键字扫盲

    前言 对于ThreadLocal.Volatile.synchronized.Atomic这四个关键字,我想一提及到大家肯定都想到的是解决在多线程并发环境下资源的共享问题,但是要细说每一个的特点.区别 ...

  8. 【Unity技巧】制作一个简单的NPC

    1. 写在前面 前几天看了cgcookie的一个教程,学习了下怎么根据已有人物模型制作一个仿版的NPC人物,感觉挺好玩的,整理一下放到博客里! 先看一下教程里面的最终效果. 是不是很像个幽灵~ 下面是 ...

  9. XStream

     1.引入需要的jar包,在pom.xml中配置依赖 <dependency> <groupId>com.thoughtworks.xstream</groupId& ...

  10. 利用openssl管理证书及SSL编程第3部分:将MinGW编译的openssl dll导出def和lib供MSVC使用

    将MinGW编译的openssl dll导出def和lib供MSVC使用 前面我们用mingw把openssl 编译成了动态库,得到下面2个dll文件: libeay32.dll ssleay32.d ...