我正在嘗試創建一個Windows服務來啓動芹菜。我遇到了一篇文章,使用Task Scheduler。然而,它似乎啓動了大量的芹菜實例,並一直吃下記憶直到機器死亡。有沒有辦法將其作爲Windows服務啓動?如何創建芹菜Windows服務?
回答
我從另一個網站得到了答案。 Celeryd(Celery的守護進程服務)作爲貼紙應用程序運行,搜索'Paster Windows Service'導致我here。它描述瞭如何作爲Windows服務運行Pylons應用程序。作爲paster框架和託管python web服務的新手,我一開始並沒有想過要檢查它。但該解決方案適用於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
Python腳本來創建Windows服務(CeleryService.py):
"""
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安裝的一部分來承載芹菜。這個解決方案似乎工作。希望這會幫助某人。
接受的答案不適用於使用Django應用程序運行芹菜。但它激勵我想出一個解決方案,將芹菜作爲Windows服務與Django一起運行。請注意,以下僅適用於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)
腳本可以運行之前,你需要
安裝pywin32。
正確設置PYTHONSCRIPTPATH和PROJECTDIR在celery_service.py
PYTHONSCRIPTPATH通常是你的Python的安裝路徑下的 「腳本」 文件夾,
例如C:\ Python27 \ Scripts中
它要麼追加到系統的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
我創建了一個演示Django項目芹菜運行爲Windows服務:
https://github.com/azalea/django_celery_windows_service
萬一你對一個運行的例子感興趣。
也許我錯過了一些東西,但即使在最新的文檔中,似乎仍在使用'celeryd',儘管它也提到使用Django來' daemonize'芹菜:http://ask.github.io/celery/cookbook/daemonizing.html#init-script-celeryd – 2015-09-08 22:02:33
@ViteFalcon感謝您指出。我編輯了我的措辭。隨意編輯並改進它。 – azalea 2015-09-09 00:59:05
@azalea的回答幫了我很多,但有一點我想在這裏強調的是,(celery_service.py)需要與您的用戶名/密碼進行安裝服務,否則,當你運行subprocess.Popen(args) in SvcDoRun()
功能,沒有什麼將會發生,因爲會有許可問題。要設置用戶名/密碼,您可以選擇以下兩種方法之一:
使用命令行:
python33 .\celeryService1.py --username .\USERNAME --password PASSWORD
轉到計算機管理(本地)>服務和應用程序>服務,找到你服務器(在@杜鵑花的例子,它是「芹菜分佈式任務隊列服務」),並點擊右鍵在日誌打開屬性頁,輸入「此帳戶」選項卡
- 1. Web服務+芹菜
- 2. 使用芹菜建立微服務
- 3. 蟒蛇創建芹菜任務作業
- 4. 如何構建芹菜任務
- 5. 如何鏈芹菜任務
- 6. 如何循環和創建多個Django的芹菜任務
- 7. 創建Windows服務
- 8. 如何通過另一個Windows服務創建Windows服務
- 9. 芹菜任務
- 10. 芹菜任務
- 11. 如何使用winrun4j創建Windows服務
- 12. 如何使用launch4j創建Windows服務?
- 13. 如何使用JRuby創建Windows服務?
- 14. 如何在Delphi中創建Windows服務?
- 15. 如何手動創建Apache Windows服務
- 16. Django /芹菜 - 如何殺死芹菜任務?
- 17. 如何回覆沒有芹菜的芹菜任務?
- 18. 如何在windows上運行芹菜?
- 19. 芹菜,從任務內創建子任務:收到類型爲
- 20. 芹菜創建幾個任務的任務
- 21. 在亞馬遜服務器芹菜
- 22. RabbitMQ和芹菜多服務器環境
- 23. 在windows中創建服務
- 24. 創建Windows服務時
- 25. Python芹菜 - 如何在其他任務中調用芹菜任務
- 26. 如何從先前的芹菜任務中產生芹菜任務?
- 27. 芹菜鏈任務
- 28. 推芹菜任務
- 29. 如何創建像Windows服務一樣運行的Android服務?
- 30. 創建芹菜動態隊列
Downvoter(S)請簡要說明你downvoted 。 – 2015-05-21 19:19:20
如何在這種情況下設置代理,例如Redis – 2016-03-09 13:12:48