An instance of a service monitor written in Python

  • 2020-04-02 14:30:43
  • OfStack

Preface:

Install Python2.7 under Redhat

Rhel6.4 comes with 2.6, and python2.4 is found in some machines. Go to the python website to download the source code, unzip it to Redhat, and run the following command:


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

After this installation not enabled by default Python2.7, you need to use the/usr/local/python27 / bin/Python2.7 calls the new version of python.

The following installation takes over the existing python directly


# ./configure
# make
# make install

Start:

The service child process is created and monitored by the monitoring main process. When the child process is closed, the main process can be started again. Python's subprocess module is used. For this simple code, there are no examples available on the Internet. I can't help it. I'll write it and contribute.

The first is the main process code: service_mgr.py


#!/usr/bin/python 
#-*- coding: UTF-8 -*- 
# cheungmine 
# stdin , stdout and stderr Represents the standard input, standard output, and standard error of the subroutine, respectively.  
#  
# The optional values are : 
#   subprocess.PIPE - Indicates that a new pipe needs to be created . 
#   A valid file descriptor (actually a positive integer)  
#   A file object  
#   None - No redirection will be done, and the child's file descriptor will inherit from the parent . 
#  
# stderr The value of PI could be zero STDOUT, A standard error representing a child process is also output to standard output . 
#  
# subprocess.PIPE 
# One can be used Popen the stdin , stdout and stderr 3 The special input value of a parameter of, indicating that a new pipe needs to be created . 
#  
# subprocess.STDOUT 
# One can be used Popen the stderr The special input value of a parameter that indicates that the subroutine's standard error is merged into standard output . 
################################################################################ 
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] %s033[31;m' % (pid, s) 
 
def print_info(s): 
    print '033[32m[%d: INFO] %s033[32;m' % (pid, s) 
 
def print_warning(s): 
    print '033[33m[%d: WARNING] %s033[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, # A standard error representing a child process is also output to standard output  
                stdout=subprocess.PIPE    # Indicates that a new pipe needs to be created  
            ) 
        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"]) 

Then there is the child code: testpipe. Py


#!/usr/bin/python 
#-*- coding: UTF-8 -*- 
# cheungmine 
# To simulate a woker process ,10 Seconds to hang up  
import os 
import sys 
 
import time 
import random 
 
cnt = 10 
 
while cnt >= 0: 
    time.sleep(0.5) 
    sys.stdout.write("OUT: %sn" % str(random.randint(1, 100000))) 
    sys.stdout.flush() 
 
    time.sleep(0.5) 
    sys.stderr.write("ERR: %sn" % str(random.randint(1, 100000))) 
    sys.stderr.flush() 
 
    #print str(cnt) 
    #sys.stdout.flush() 
    cnt = cnt - 1 
 
sys.exit(-1) 

Running on Linux is simple:


$ python service_mgr.py

Running the back process on Windows:

> start pythonw service_mgr.py

The code needs to be modified:

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


Related articles: