2012-02-21 35 views
7

Celeryを起動するWindowsサービスを作成しようとしています。私はTask Schedulerを使って記事を見てきました。しかし、それは多くのセロリのインスタンスを起動し、マシンが死ぬまでメモリを食べ続けているようです。それをWindowsサービスとして起動する方法はありますか?Celery Windowsサービスの作成方法?

答えて

12

私は別のウェブサイトから回答を得ました。 Celeryd(Celeryのデーモンサービス)はペーストアプリケーションとして動作し、「Paster Windows Service」を検索するとhereが表示されます。 PylonsアプリケーションをWindowsサービスとして実行する方法について説明します。より洗練されたフレームワークと、Python Webサービスのホスティングを初めて知っていたので、最初にチェックしてみました。しかし、その解決策はセロリのためにスクリプトの中で少し変化を加えて動作します。

セロリの設定を簡単に変更できるようにスクリプトを修正しました。基本的な変更点は次のとおりです。

  1. は(下図参照)セロリサービス
  2. の設定をINIファイルを作成し、Windowsサービスを作成するためのPythonスクリプトを作成します。

INIファイルの設定(celeryd.ini):Windowsサービス(CeleryService.py)を作成するための

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

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を実行してください。

RhodeCodeのインストールを強化する一環として、Celeryをホストしようとしていました。この解決法はうまくいくと思われる。これが誰かを助けることを願っています。

+0

Downvoter(s)はあなたがdownvoted理由を明記してください。 –

+0

どのようにしてこのようなケースでブローカを設定するのですか?Redisの例は –

3

受け入れられた回答は、Djangoアプリケーションでセロリを実行する場合には適用されません。しかし、それは私に、DjangoのWindowsサービスとしてセロリを実行するためのソリューションを考え出すよう促しました。次はDjangoプロジェクトの場合のみです。これは、いくつかの変更を加えて他のアプリケーションで動作する可能性があります。

あなたのDjangoプロジェクトの最上位フォルダ、以下の内容でmanage.pyと同じレベル、内部のファイルcelery_service.py(またはものは何でもあなたが好き)を作成します。スクリプトを実行する前に、

'''Usage : python celery_service.py install (start/stop/remove) 
Run celery as a Windows service 
''' 
import win32service 
import win32serviceutil 
import win32api 
import win32con 
import win32event 
import subprocess 
import sys 
import os 
import shlex 
import logging 
import time 

# The directory for celery.log and celery_service.log 
# Default: the directory of this script 
INSTDIR = os.path.dirname(os.path.realpath(__file__)) 
# The path of python Scripts 
# Usually it is in PYTHON_INSTALL_DIR/Scripts. e.g. 
# r'C:\Python27\Scripts' 
# If it is already in system PATH, then it can be set as '' 
PYTHONSCRIPTPATH = '' 
# The directory name of django project 
# Note: it is the directory at the same level of manage.py 
# not the parent directory 
PROJECTDIR = 'proj' 

logging.basicConfig(
    filename = os.path.join(INSTDIR, 'celery_service.log'), 
    level = logging.DEBUG, 
    format = '[%(asctime)-15s: %(levelname)-7.7s] %(message)s' 
) 

class CeleryService(win32serviceutil.ServiceFramework): 

    _svc_name_ = "Celery" 
    _svc_display_name_ = "Celery Distributed Task Queue Service" 

    def __init__(self, args): 
     win32serviceutil.ServiceFramework.__init__(self, args) 
     self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)   

    def SvcStop(self): 
     logging.info('Stopping {name} service ...'.format(name=self._svc_name_))   
     self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) 
     win32event.SetEvent(self.hWaitStop) 
     self.ReportServiceStatus(win32service.SERVICE_STOPPED) 
     sys.exit()   

    def SvcDoRun(self): 
     logging.info('Starting {name} service ...'.format(name=self._svc_name_)) 
     os.chdir(INSTDIR) # so that proj worker can be found 
     logging.info('cwd: ' + os.getcwd()) 
     self.ReportServiceStatus(win32service.SERVICE_RUNNING) 
     command = '"{celery_path}" -A {proj_dir} worker -f "{log_path}" -l info'.format(
      celery_path=os.path.join(PYTHONSCRIPTPATH, 'celery.exe'), 
      proj_dir=PROJECTDIR, 
      log_path=os.path.join(INSTDIR,'celery.log')) 
     logging.info('command: ' + command) 
     args = shlex.split(command) 
     proc = subprocess.Popen(args) 
     logging.info('pid: {pid}'.format(pid=proc.pid)) 
     self.timeout = 3000 
     while True: 
      rc = win32event.WaitForSingleObject(self.hWaitStop, self.timeout) 
      if rc == win32event.WAIT_OBJECT_0: 
       # stop signal encountered 
       # terminate process 'proc' 
       PROCESS_TERMINATE = 1 
       handle = win32api.OpenProcess(PROCESS_TERMINATE, False, proc.pid) 
       win32api.TerminateProcess(handle, -1) 
       win32api.CloseHandle(handle)     
       break 

if __name__ == '__main__': 
    win32serviceutil.HandleCommandLine(CeleryService) 

あなたは

  1. インストールpywin32が必要です。

PYTHONSCRIPTPATHは通常、あなたのPythonのインストールパスの下の "スクリプト" フォルダですcelery_service.pyで

  • 正しく設定PYTHONSCRIPTPATHとPROJECTDIR、

    例えばC:\ Python27 \スクリプト

    どちらかお使いのシステムのPATHに追加し、

    または編集celery_service.py

    PYTHONSCRIPTPATH = r'C:\Python27\Scripts' 
    

    PROJECTDIRは、Djangoプロジェクトのディレクトリ名です。

    これは、親ディレクトリではなく、manage.pyと同じレベルのディレクトリです。

    今、あなたがインストールすることができます/起動/停止/でサービスを削除します。

    python celery_service.py install 
    python celery_service.py start 
    python celery_service.py stop 
    python celery_service.py remove 
    

    私はセロリがWindowsサービスとして実行しているデモDjangoプロジェクトを作成しました:場合

    https://github.com/azalea/django_celery_windows_service

    あなたは実行中の例に興味があります。

  • +0

    ですが、最新のドキュメントでも、 'celeryd'がまだ使われているようですが、Djangoを使って ' daemonize 'Celery:http://ask.github.io/celery/cookbook/daemonizing.html#init-script-celeryd –

    +0

    @ViteFalconありがとうございます。私は言葉を編集しました。編集して改善してください。 – azalea

    1

    @ azaleaの回答は私を大いに助けましたが、私がここで強調したいのは、サービス(celery_service.py)をユーザ/パスワードとともにインストールする必要があります。そうでなければ、subprocess.Popen(args) in SvcDoRun()機能、許可の問題があるために起こります。あなたの見つけ、コンピュータの管理に

    python33 .\celeryService1.py --username .\USERNAME --password PASSWORD 
    
  • ゴー(ローカル)]> [サービスとアプリケーション]> [サービス:コマンドラインを使用

    1. :ユーザー/パスワードを設定するには、次の2つの方法のいずれかを選択することができますサーバー(@ツツジの例では、それは「タスクキューサービス分散セロリ」である)、およびプロパティ]ページを開くには、右クリックして、入力「このアカウント」ログのタブで

  • 関連する問題