J'essaie de créer un service Windows pour lancer le céleri. J'ai rencontré un article qui utilise Planificateur de tâches . Cependant, il semble lancer de nombreuses instances de céleri et continue de manger de la mémoire jusqu'à matriction de la machine. Y a-t-il un moyen de le lancer comme un service Windows? P>
5 Réponses :
J'ai la réponse d'un autre site Web. Celeryd (Daemon Service for Ceery) est exécuté en tant qu'application de Soulet, à la recherche de 'Spast Windows Service' mène-moi ici . Il décrit comment exécuter une application de pylônes en tant que service Windows. Étant nouveau dans le cadre de diffamation et hébergement de services Web Python, il n'a pas traversé d'avis pour le vérifier au début. Mais cette solution fonctionne pour le céleri avec un léger changement ici et là dans le script.
J'ai modifié le script pour faciliter la modification des paramètres de céleri. Les changements essentiels sont: P>
Paramètres de fichier INI (céleryd.ini): p> script python pour créer un service Windows (céleryservice.py): p> """
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)
Comment définissez-vous un courtier dans un tel cas, Redis par exemple
La réponse acceptée ne demande pas en cours d'exécution de céleri avec une application Django. Mais il m'a inspiré pour trouver une solution pour faire fonctionner le céleri en tant que service Windows avec Django. Notez que ce qui suit est pour les projets Django seulement. Il peut fonctionner avec d'autres applications, avec quelques modifications.
La discussion suivante suppose Python> = 3.6 et RabbitMQ sont déjà installés, et Créer un celery_service.py de fichier (ou tout ce que vous aimez) dans votre dossier de niveau supérieur de projet Django, même niveau que manage.py, avec le contenu suivant: p> rabbitmq-server code> est en cours d'exécution sur
localhost code>. p>
python celery_service.py install
python celery_service.py start
python celery_service.py stop
python celery_service.py remove
Peut-être que je manque quelque chose, mais même dans la dernière documentation, il semble que Celeryd CODE> est toujours utilisé, bien qu'il ne mentionne pas également à l'aide de Django pour "démoniser" céleri: Ask.github.IO/celery/Cookbook/...
@Vitefalcon merci de le pointer. J'ai édité mon libellé. N'hésitez pas à éditer et à l'améliorer.
La réponse de @azalea m'a beaucoup aidé, mais une chose que j'aime souligner ici est, le service (célery_service.py) doit être installé avec votre utilisateur / mot de passe, sinon, lorsque vous exécutez Utilisation de la ligne de commande: P>
aller à la gestion de l'ordinateur (local)> Services et applications> Services, Recherchez votre serveur (dans l'exemple de @ Azalea, il s'agit de "service de file d'attente de tâches distribuée de céleri"), puis cliquez avec le bouton droit de la souris pour ouvrir la page des propriétés, entrée " Ce compte "dans l'onglet Connexion P> LI>
ol> p> sous-processus. Popen (ARG) dans SVCDorun () Code> fonction, rien ne se produira car il y aura une question de permission. Pour définir l'utilisateur / mot de passe, vous pouvez choisir l'une des deux méthodes suivantes:
Un bon projet ici mais n'a pas réussi à l'utiliser: Lien vers le GitHub of the Django-Windows-Tools . Cela m'a donné un délai d'attente à la dernière ligne de commande. N'a pas assez de temps pour rechercher pourquoi. P>
Le paquet permet aux paramètres FastCGI, de céleri et de fichiers statiques d'un projet Django sur IIS. P>
Merci à Azalea, car cela m'a conduit à la voie de la possibilité de créer 2 services Windows avec le céleri 4 sur Windows.
Un pour pouvoir commencer / arrêter plusieurs travailleurs Deuxièmement, pour pouvoir démarrer / arrêter le service de battement et ranger le PID à l'aide de céleri 4. P>
Seulement une mise en garde dans celle-ci que je n'ai pas de solution pour que vous ne puissiez pas redémarrer les travailleurs comme vous avez besoin de Assurez-vous que les processus engendrés pour plusieurs sont arrêtés avant de reculer. p>
travailleurs.py: p> beatService.py: p> '''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
import signal
# The directory for celery_beat.log and celery_beat_service.log
# Default: the directory of this script
INSTDIR = os.path.dirname(os.path.realpath(__file__))
LOGPATH = 'X:\Application\Logs'
# 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 = 'C:\Python36\Scripts'
# The directory name of django project
# Note: it is the directory at the same level of manage.py
# not the parent directory
PROJECTDIR = 'PROJECT'
logging.basicConfig(
filename = os.path.join(LOGPATH, 'celery_beat_service.log'),
level = logging.DEBUG,
format = '[%(asctime)-15s: %(levelname)-7.7s] %(message)s'
)
class CeleryService(win32serviceutil.ServiceFramework):
_svc_name_ = "CeleryBeat"
_svc_display_name_ = "CeleryBeat"
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
def SvcStop(self):
logging.info('Stopping 1 {name} service ...'.format(name=self._svc_name_))
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
pidno = open("X:\Aplication\Project\celerybeat.pid", "r")
_pid_id_ = pidid=pidno.read()
pidno.close()
logging.info(_pid_id_)
logging.info('taskkill /F /PID {pidid} ..'.format(pidid=_pid_id_))
cmdcom = 'taskkill /F /PID {pidid}'.format(pidid=_pid_id_)
logging.info(cmdcom)
killargs = shlex.split(cmdcom)
process = subprocess.Popen(killargs)
output, error = process.communicate()
logging.info(output)
logging.info('Stopping 2 {name} service ...'.format(name=self._svc_name_))
os.remove("X:\Application\PROJECT\celerybeat.pid")
logging.info('X:\Application\PROJECT\celerybeat.pid file removed')
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} beat --workdir=X:/Application/Project -f X:/Application/logs/beat.log -l info'.format(
celery_path=os.path.join(PYTHONSCRIPTPATH, 'celery.exe'),
proj_dir=PROJECTDIR,
log_path=os.path.join(LOGPATH,'celery_beat.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)