当前位置: 首页 > 面试题库 >

如何创建芹菜Windows服务?

颜嘉福
2023-03-14
问题内容

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


问题答案:

我从另一个网站得到了答案。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安装的一部分。此解决方案似乎有效。希望这会帮助某人。



 类似资料:
  • 问题内容: 如何在Windows中运行celery worker而不创建Windows Service?有什么比喻吗? 问题答案: 它的完成方式与Linux中相同。将目录更改为包含celery任务的模块并调用效果很好。

  • 现在,我想将< code>register事件发布到某个特殊的交换,我可以使用celery远程检索和处理它。 实际上,我已经使用了函数来实现这一点,但是它必须传递来指示应该执行哪个任务并消费它。所以它似乎不太适合我的目标。 我想要的就是这样: 向某些发布消息; 远程机器1订阅此或并捕获消息,用于执行任务; 远程机器2-与机器1相同但执行另一个任务-接收(可能需要回复某些) 例如,就像这个工作流一样

  • 我最近开始研究分布式计算以提高计算速度。我选择了芹菜。然而,我对一些术语不太熟悉。所以,我有几个相关的问题。 来自芹菜文档: ... Celery通过消息进行通信,通常使用代理在客户机和工作人员之间进行调解。为了启动任务,客户机将消息添加到队列中,然后代理将该消息传递给工作者。 什么是客户端(这里)?什么是经纪商?为什么消息通过代理传递?为什么 Celery 会使用后端和队列进行进程间通信? 当我

  • 问题内容: 我刚刚继承了一个Java应用程序,该应用程序需要作为服务安装在XP和Vista上。自从我以任何形式使用Windows至今已有8年了,而且我从未创建过一项服务,更不用说从Java应用程序之类的东西了了(我为该应用程序提供了一个jar,并且有一个依赖项jar-log4j )。使它作为服务运行所需的魔术是什么?我已经掌握了源代码,因此尽管可以避免进行代码修改,但还是可以的。 问题答案: 我对

  • 发送到芹菜的函数是使用装饰器指向我要使用的队列,例如: 我创建了一个脚本来检查队列中还有多少任务,这只是命令的一个while循环 并用“芹菜”解析行 但由于芹菜会产生随机队列,我无法使用它。为什么芹菜正在创建新的队列,而不是真正将其发送到我想要的队列?

  • 问题内容: 我想在我的应用程序中创建一个工具栏。如果单击该工具栏上的按钮,它将弹出一个菜单,就像Eclipse的工具栏一样。我不知道如何在Swing中执行此操作。有谁可以帮助我吗?我尝试过Google,但一无所获。 问题答案: 在Swing中,这比需要做的难。因此,我没有为您提供教程,而是创建了一个完整的示例。