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"])