如何创建芹菜Windows服务?

发布于 2021-01-29 15:06:17

我正在尝试创建Windows服务来启动Celery。我碰到了一篇使用Task
Scheduler
来做的文章。但是,它似乎启动了许多芹菜实例,并不断消耗内存直到机器死机。有什么方法可以将其作为Windows服务启动吗?

关注者
0
被浏览
57
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    我从另一个网站得到了答案。Celeryd(Celery的守护程序服务)作为粘贴应用程序运行,在这里搜索“
    Paster Windows
    Service”会导致我。它描述了如何将Pylons应用程序作为Windows服务运行。作为Paster框架的新成员并托管python
    Web服务,一开始我就没想到要检查它。但是该解决方案适用于Celery,脚本中到处都有微小的变化。

    我已经修改了脚本,使修改Celery设置更加容易。基本变化是:

    1. 使用Celery服务的设置创建一个INI文件(如下所示)
    2. 创建一个python脚本来创建Windows服务。

    INI文件设置(celeryd.ini):

    [celery:service]
    service_name = CeleryService
    service_display_name = Celery Service
    service_description = WSCGI Windows Celery Service
    service_logfile = celeryd.log
    

    创建Windows服务(CeleryService.py)的Python脚本:

    """
    The most basic (working) Windows service possible.
    Requires Mark Hammond's pywin32 package.  
    Most of the code was taken from a  CherryPy 2.2 example of how to set up a service
    """
    import pkg_resources
    import win32serviceutil
    from paste.script.serve import ServeCommand as Server
    import os, sys
    import ConfigParser
    
    import win32service
    import win32event
    
    SCRIPT_DIR          = os.path.abspath(os.path.dirname(__file__))
    INI_FILE            = 'celeryd.ini'
    SERV_SECTION        = 'celery:service'
    SERV_NAME           = 'service_name'
    SERV_DISPLAY_NAME   = 'service_display_name'
    SERV_DESC           = 'service_description'
    SERV_LOG_FILE       = 'service_logfile'
    SERV_APPLICATION    = 'celeryd'
    SERV_LOG_FILE_VAR   = 'CELERYD_LOG_FILE'
    
    # Default Values
    SERV_NAME_DEFAULT           = 'CeleryService'
    SERV_DISPLAY_NAME_DEFAULT   = 'Celery Service'
    SERV_DESC_DEFAULT           = 'WSCGI Windows Celery Service'
    SERV_LOG_FILE_DEFAULT       = r'D:\logs\celery.log'
    
    class DefaultSettings(object):
        def __init__(self):
            if SCRIPT_DIR:
                os.chdir(SCRIPT_DIR)
            # find the ini file
            self.ini = os.path.join(SCRIPT_DIR,INI_FILE)
            # create a config parser opject and populate it with the ini file
            c = ConfigParser.SafeConfigParser()
            c.read(self.ini)
            self.c = c
    
        def getDefaults(self):
            '''
            Check for and get the default settings
            '''
            if (
                (not self.c.has_section(SERV_SECTION)) or
                (not self.c.has_option(SERV_SECTION, SERV_NAME)) or
                (not self.c.has_option(SERV_SECTION, SERV_DISPLAY_NAME)) or
                (not self.c.has_option(SERV_SECTION, SERV_DESC)) or
                (not self.c.has_option(SERV_SECTION, SERV_LOG_FILE))
                ):
                print 'setting defaults'
                self.setDefaults()
            service_name = self.c.get(SERV_SECTION, SERV_NAME)
            service_display_name = self.c.get(SERV_SECTION, SERV_DISPLAY_NAME)
            service_description = self.c.get(SERV_SECTION, SERV_DESC)
            iniFile = self.ini
            service_logfile = self.c.get(SERV_SECTION, SERV_LOG_FILE)
            return service_name, service_display_name, service_description, iniFile, service_logfile
    
        def setDefaults(self):
            '''
            set and add the default setting to the ini file
            '''
            if not self.c.has_section(SERV_SECTION):
                self.c.add_section(SERV_SECTION)
            self.c.set(SERV_SECTION, SERV_NAME, SERV_NAME_DEFAULT)
            self.c.set(SERV_SECTION, SERV_DISPLAY_NAME, SERV_DISPLAY_NAME_DEFAULT)
            self.c.set(SERV_SECTION, SERV_DESC, SERV_DESC_DEFAULT)
            self.c.set(SERV_SECTION, SERV_LOG_FILE, SERV_LOG_FILE_DEFAULT)
            cfg = file(self.ini, 'wr')
            self.c.write(cfg)
            cfg.close()
            print '''
    you must set the celery:service section service_name, service_display_name,
    and service_description options to define the service 
    in the %s file
    ''' % self.ini
            sys.exit()
    
    
    class CeleryService(win32serviceutil.ServiceFramework):
        """NT Service."""
    
        d = DefaultSettings()
        service_name, service_display_name, service_description, iniFile, logFile = d.getDefaults()
    
        _svc_name_ = service_name
        _svc_display_name_ = service_display_name
        _svc_description_ = service_description
    
        def __init__(self, args):
            win32serviceutil.ServiceFramework.__init__(self, args)
            # create an event that SvcDoRun can wait on and SvcStop
            # can set.
            self.stop_event = win32event.CreateEvent(None, 0, 0, None)
    
        def SvcDoRun(self):
            os.chdir(SCRIPT_DIR)
            s = Server(SERV_APPLICATION)
            os.environ[SERV_LOG_FILE_VAR] = self.logFile
            s.run([self.iniFile])
            win32event.WaitForSingleObject(self.stop_event, win32event.INFINITE)
    
        def SvcStop(self):
            self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
            #win32event.SetEvent(self.stop_event)
            self.ReportServiceStatus(win32service.SERVICE_STOPPED)
            sys.exit()
    
    if __name__ == '__main__':
        win32serviceutil.HandleCommandLine(CeleryService)
    

    要安装该服务,请运行python CeleryService.py install,然后python CeleryService.py start启动该服务。 注意 :这些命令应在具有管理员权限的命令行中运行。

    如果需要删除服务,请运行python CeleryService.py remove

    我正在尝试托管Celery,作为增强RhodeCode安装的一部分。此解决方案似乎有效。希望这会帮助某人。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看