Source

django-celery-about / source / daemonize.rst

Full commit

デーモン化/init.d化

virtualenvスクリプトのinit.d化

$VIRTUALENV/bin/にrunner(django managerのアダプタ) を作る

#!/home/hdknr/ve/tact/bin/python

__requires__ = 'paloma==0.1.1'
from pkg_resources import require; require('paloma==0.1.1')
del require

__file__ = '/home/hdknr/ve/tact/src/paloma/src/scripts/paloma_worker.py'
execfile(__file__)
#:エラー処理を抜いています
#
import sys,os

#: Django のプロジェクトを sys.pathに設定します。
#
sys.path.append(os.path.dirname(sys.argv[1]))    #: Important :
sys.path.append(sys.argv[1])    #: Important

#: Django プロジェクトのsettings.pyをロードする
#
import imp
imp.find_module('settings') # Assumed to be in the same directory.
import settings

#: run.py をロードして、 execute_managerに渡す引数をもらう
#
import run
sys.argv = run.configure(sys.argv) #: これはプロジェクトごとに定義する。

#: django manager を実行する
#
from django.core.management import execute_manager
execute_manager(settings)

Djangoプロジェクトにrun.pyを用意する(start/stopなど)

import os
import sys
#
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app.settings")

APP_DIR=os.path.dirname(__file__)
LOG_FILE="/tmp/celery.log"  #: celery worker logfile
PID_FILE="/tmp/celery.pid"  #: celery worker PID file
NODE="celery"           #: celery = default node
LOG_LEVEL="DEBUG"       #: celery log level

def configure(args):
    ''' return django-celery parameter for specified args

        - args[0] : paloma_worker.py
        - args[1] : path this django project application
        - args[2] : command
    '''

    if  len(args) < 3 or args[2] == "start" :
        #: start worker
        return [ args[0],
                "celeryd",
                "--loglevel" , LOG_LEVEL,
                "--pidfile" , PID_FILE,
                "--logfile" , LOG_FILE ,
                "-E",                       # event option
                "--beat" ,
                "--scheduler","djcelery.schedulers.DatabaseScheduler",
            ]

    if  len(args) >2 and args[2] == "stop":
        #: stop worker
        return [ args[0],
                "celeryd_multi",
                "stop",NODE,
                "--pidfile=%s" % PID_FILE,
            ]

runnerにDjangoのprojet pathを指定する(/etc/init.d/your_service)

#!/bin/sh -e
#
DAEMON=/home/hdknr/ve/tact/bin/paloma_worker.py
USER=hdknr
NAME=paloma
PROJECTS="/home/hdknr/ve/tact/src/paloma/example/app\
         "
RUN=$1

test -x $DAEMON || exit 0
id $USER > /dev/null 2>&1 || exit 0

case $RUN in
    'install' ) insserv $NAME;;
    'uninstall') insserv -r $NAME;;
    ''|'start'|'stop') echo "running command";
        for PRJ in $PROJECTS; do
            (sudo -u $USER $DAEMON $PRJ $RUN)&
        done
esac

停止は TERM シグナル

  • TERMを何度か送って終わる事をみること。
  • KILL する前に実行中のタスクが無いかどうか調べる。
  • settings.CELERY_ACKS_LATE==True だとキューにメッセージが残ったままKILLされるから次回再処理されるかも。