Skip to content

Instantly share code, notes, and snippets.

@Ins1ne
Last active October 9, 2015 12:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Ins1ne/7cd62d30ffa7172a3b09 to your computer and use it in GitHub Desktop.
Save Ins1ne/7cd62d30ffa7172a3b09 to your computer and use it in GitHub Desktop.
import ConfigParser
import multiprocessing
import os
import servicemanager
import sys
import time
import win32serviceutil
import win32service
import win32event
import win32api
PROCESSES = {}
class MyProcess(multiprocessing.Process):
"""Simple test process does nothing."""
def __init__(self, *args, **kwargs):
super(MyProcess, self).__init__(*args, **kwargs)
self.exit = multiprocessing.Event()
def run(self):
while not self.exit.is_set():
time.sleep(1)
def shutdown(self):
"""Close all work and exit."""
self.exit.set()
class ServiceExample(win32serviceutil.ServiceFramework):
"""Service example which does nothing and simply wait to stop."""
_svc_name_ = "ServiceExample"
_svc_display_name_ = "Python service example"
_svc_description_ = "Example of service for run python script"
timeout = 10000
shutdown_timeout = 10
process_names = []
config_file = None
stop = False
def __init__(self, args):
self.config_file = os.path.join(os.path.dirname(__file__), 'service.cfg')
self.log(self.config_file)
win32serviceutil.ServiceFramework.__init__(self, args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
def sleep(self, sec):
win32api.Sleep(sec * 1000, True)
def SvcStop(self):
"""Stop service handler"""
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
self.log('Stop serivce')
self.stop = True
# stop supervisor here
self.stop_supervisor()
# show all killed
self.monitor(False)
self.ReportServiceStatus(win32service.SERVICE_STOPPED)
def SvcDoRun(self):
"""Run service handler"""
self.ReportServiceStatus(win32service.SERVICE_START_PENDING)
try:
self.ReportServiceStatus(win32service.SERVICE_RUNNING)
self.log('start')
self.start()
self.log('wait')
win32event.WaitForSingleObject(self.stop_event, win32event.INFINITE)
self.log('done')
except Exception, x:
self.log('Exception : %s' % x)
self.SvcStop()
def start(self):
"""Start service processes"""
# start supervisor here if it not started
if not PROCESSES:
self.start_supervisor()
while 1:
# monitor processes
self.monitor()
self.sleep(60)
def log(self, msg):
"""Log messages."""
servicemanager.LogInfoMsg(str(msg))
def get_processes_names(self):
"""Get process names from config file."""
if not self.process_names:
self.log('Parse config file from {}'.format(self.config_file))
config = ConfigParser.ConfigParser()
config.read(self.config_file)
try:
section = config.sections()[0]
except IndexError:
self.log('Wrong config file provided - no sections.')
return
self.process_names = [x[1] for x in config.items(section)]
def start_supervisor(self):
"""Command to start supervisor"""
self.get_processes_names()
for name in self.process_names:
self.log('Starting process with name {}'.format(name))
PROCESSES[name] = MyProcess(name=name)
PROCESSES[name].start()
def stop_supervisor(self):
"""Command to stop supervisor"""
# trying gracefull shutdown process
for name, process in PROCESSES.iteritems():
self.log('Trying to shutdown process {}'.format(name))
process.shutdown()
process.join(self.shutdown_timeout)
# if still alive processes - kill them
if any([p.is_alive() for p in PROCESSES.values()]):
for name, process in PROCESSES.iteritems():
self.log('Trying to kill process {}'.format(name))
process.terminate()
process.join(5)
# wait for kill all processes
self.sleep(5)
def monitor(self, restart=True):
"""Monitor processes and restart if needed"""
count = 0
for name, process in PROCESSES.iteritems():
if process.is_alive():
count += 1
self.log('{} pid {}'.format(name, str(process.pid)))
else:
if restart or not self.stop:
self.log('Process with name {} is down, restarting...'.format(name))
PROCESSES[name].terminate()
PROCESSES[name] = MyProcess(name=name)
PROCESSES[name].start()
self.log('Running {} from {} processes'.format(
str(count), str(len(PROCESSES.items()))
))
if __name__ == '__main__':
win32serviceutil.HandleCommandLine(ServiceExample)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment