如何创建芹菜Windows服务?
我正在尝试创建Windows服务来启动Celery。我碰到了一篇使用Task
Scheduler来做的文章。但是,它似乎启动了许多芹菜实例,并不断消耗内存直到机器死机。有什么方法可以将其作为Windows服务启动吗?
-
我从另一个网站得到了答案。Celeryd(Celery的守护程序服务)作为粘贴应用程序运行,在这里搜索“
Paster Windows
Service”会导致我。它描述了如何将Pylons应用程序作为Windows服务运行。作为Paster框架的新成员并托管python
Web服务,一开始我就没想到要检查它。但是该解决方案适用于Celery,脚本中到处都有微小的变化。我已经修改了脚本,使修改Celery设置更加容易。基本变化是:
- 使用Celery服务的设置创建一个INI文件(如下所示)
- 创建一个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安装的一部分。此解决方案似乎有效。希望这会帮助某人。