SHARE
TWEET

Untitled

a guest Nov 24th, 2016 127 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/env python
  2. # coding:utf-8
  3.  
  4. import sys
  5. import os
  6. import re
  7. import time
  8. import socket
  9. import subprocess
  10. import threading
  11. import logging
  12. import xmlrpclib
  13. import SimpleXMLRPCServer
  14. import ConfigParser
  15.  
  16. USE_PYTHONW = 'C:\\Python27\\pythonw.exe'
  17. SUPERVISORD_CONF = './supervisord.conf'
  18. DEFAULT_PORT = 9001
  19. CURRENT_WATCHDOGS = []
  20.  
  21. logging.basicConfig(level=logging.INFO, format='%(levelname)s - %(asctime)s %(message)s')
  22.  
  23.  
  24. class WatchDog(threading.Thread):
  25.     """a windows process watch dog"""
  26.     TICK_SECONDS = 1
  27.     START_SECONDS = 5
  28.  
  29.     def __init__(self, name, commandline):
  30.         threading.Thread.__init__(self)
  31.         self.setName(name)
  32.         self._commanline = commandline
  33.         self._birthtime = None
  34.         self._stoped = False
  35.         self._pipe = None
  36.  
  37.     def run(self):
  38.         close_fds = False if sys.platform == 'win32' else True
  39.         self._pipe = subprocess.Popen(self._commanline, shell=False, close_fds=close_fds)
  40.         self._birthtime = time.time()
  41.         while True:
  42.             try:
  43.                 time.sleep(self.TICK_SECONDS)
  44.                 if self._stoped:
  45.                     self._pipe.terminate()
  46.                     self._pipe = None
  47.                     return True
  48.                 else:
  49.                     if self._pipe.poll() is not None:
  50.                         if time.time() - self._birthtime < self.START_SECONDS:
  51.                             logging.error('WatchDog(%r) start failed', self.getName())
  52.                             self._stoped = True
  53.                             self._pipe = None
  54.                             return False
  55.                         else:
  56.                             logging.error('WatchDog(%r) aborted, try restart', self.getName())
  57.                             self._pipe = subprocess.Popen(self._commanline, shell=False, close_fds=close_fds)
  58.                             self._birthtime = time.time()
  59.                     else:
  60.                         logging.debug('WatchDog(%r) is alive', self.getName())
  61.             except Exception as e:
  62.                 logging.exception('WatchDog.run error: %r', e)
  63.  
  64.     def start(self):
  65.         threading.Thread.start(self)
  66.         return True
  67.  
  68.     def stop(self):
  69.         self._stoped = True
  70.         timeout = self.START_SECONDS
  71.         while timeout > 0:
  72.             if self._pipe is None:
  73.                 return True
  74.             else:
  75.                 time.sleep(self.TICK_SECONDS)
  76.                 timeout -= self.TICK_SECONDS
  77.         return False
  78.  
  79.  
  80. def check_daemon(timeout=1):
  81.     try:
  82.         socket.create_connection(('127.0.0.1', DEFAULT_PORT), timeout=timeout).close()
  83.         return True
  84.     except socket.error:
  85.         return False
  86.  
  87.  
  88. def read_service(filename):
  89.     assert os.path.isfile(filename)
  90.     config = ConfigParser.ConfigParser()
  91.     config.read(filename)
  92.     services = {}
  93.     for section in config.sections():
  94.         if section.startswith('program:') and config.has_option(section, 'command'):
  95.             name = section[8:].strip()
  96.             command = config.get(section, 'command').strip()
  97.             if USE_PYTHONW and command.startswith('python'):
  98.                 command = ' '.join([USE_PYTHONW] + command.split()[1:])
  99.             services[name] = command
  100.     return services
  101.  
  102.  
  103. def clear_stoped_watchdog():
  104.     global CURRENT_WATCHDOGS
  105.     CURRENT_WATCHDOGS = [x for x in CURRENT_WATCHDOGS if not x._stoped and x._pipe]
  106.  
  107.  
  108. def do_start(name, commandline):
  109.     clear_stoped_watchdog()
  110.     for watchdog in CURRENT_WATCHDOGS:
  111.         if watchdog.getName() == name:
  112.             msg = 'WatchDog(%r) already started' % name
  113.             logging.error(msg)
  114.             return msg
  115.     watchdog = WatchDog(name, commandline)
  116.     watchdog.start()
  117.     CURRENT_WATCHDOGS.append(watchdog)
  118.     msg = 'WatchDog(%r) started' % watchdog.getName()
  119.     logging.info(msg)
  120.     return msg
  121.  
  122.  
  123. def do_stop(name, commandline):
  124.     assert name and commandline
  125.     clear_stoped_watchdog()
  126.     for watchdog in CURRENT_WATCHDOGS:
  127.         if watchdog.getName() == name:
  128.             logging.info('try stoping WatchDog(%r)', name)
  129.             result = watchdog.stop()
  130.             clear_stoped_watchdog()
  131.             if result:
  132.                 return 'Stop WatchDog(%r) OK' % watchdog.getName()
  133.             else:
  134.                 return 'Stop WatchDog(%r) Error' % watchdog.getName()
  135.     return 'Stop WatchDog(%r) existed, Stop OK' % name
  136.  
  137.  
  138. def do_restart(name, commandline):
  139.     msg = do_stop(name, commandline)
  140.     if 'ok' in msg.lower():
  141.         return do_start(name, commandline)
  142.     else:
  143.         return msg
  144.  
  145.  
  146. def do_list(name, commandline):
  147.     assert name and commandline
  148.     clear_stoped_watchdog()
  149.     return os.linesep.join('%s PID:%s' % (x.getName(), x._pipe.pid) for x in CURRENT_WATCHDOGS)
  150.  
  151.  
  152. def supervisord():
  153.     server = SimpleXMLRPCServer.SimpleXMLRPCServer(('', DEFAULT_PORT), logRequests=True)
  154.     server.register_function(do_start)
  155.     server.register_function(do_stop)
  156.     server.register_function(do_restart)
  157.     server.register_function(do_list)
  158.     server.serve_forever()
  159.  
  160.  
  161. def supervisorctl():
  162.     argstr = ' '.join(sys.argv[1:])
  163.     m = re.search('--service=(\w+)', argstr)
  164.     service = m.group(1) if m else 'node_agent'
  165.     m = re.search('-c\s+(\w+)', argstr)
  166.     action = m.group(1) if m else ''
  167.     filename = os.path.join(os.path.dirname(os.path.abspath(__file__)), SUPERVISORD_CONF)
  168.     conf_services = read_service(filename)
  169.     services = conf_services.keys() if service == 'all' else [service]
  170.     for service in services:
  171.         if service not in conf_services:
  172.             logging.error('cannot found service=%r in %r', service, filename)
  173.         proxy = xmlrpclib.ServerProxy('http://localhost:%d' % DEFAULT_PORT)
  174.         if action == 'start':
  175.             print(proxy.do_start(service, conf_services[service]))
  176.         elif action == 'stop':
  177.             print(proxy.do_stop(service, conf_services[service]))
  178.         elif action == 'restart':
  179.             print(proxy.do_restart(service, conf_services[service]))
  180.         else:
  181.             print(proxy.do_list(service, conf_services[service]))
  182.  
  183.  
  184. def main():
  185.     if '--daemon' in sys.argv[1:]:
  186.         supervisord()
  187.         sys.exit(0)
  188.     if not check_daemon():
  189.         if USE_PYTHONW:
  190.             close_fds = False if sys.platform == 'win32' else True
  191.             cmd = '%s "%s" --daemon' % (USE_PYTHONW, os.path.abspath(__file__))
  192.             subprocess.Popen(cmd, close_fds=close_fds)
  193.         else:
  194.             cmd = 'start "%s" "%s" --daemon' % (sys.executable, os.path.abspath(__file__))
  195.             os.system(cmd)
  196.     supervisorctl()
  197.  
  198.  
  199. if __name__ == '__main__':
  200.     main()
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top