Daemonization

大多数Linux发行版使用systemd来管理系统及用户服务的生命周期。

你可以使用下面的命令检查自己的发行版是否支持systemd:

$ systemd --version
systemd 237
+PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD -IDN2 +IDN -PCRE2 default-hierarchy=hybrid

如果输出和上面的类似,请从我们的 systemd 文档获取指导

然而,init.d脚本仍然可以在这些Linux发行版中工作,因为systemd提供了systemd-sysv兼容层,该层可以从我们提供的init.d脚本自动生成服务。

如果你的Celery需要运行在不同的发行版,其中有些不支持systemd或者其他Unix系统,你可能需要我们的init.d文档

Generic init-script: 生成init脚本

查看Celery发行版中的extra/generic-init.d/open in new window目录。

这个目录包含生成init-scripts的脚本,可以在Linux、FreeBSD、OpenBSD以及其他类Unix平台运行。

Init-script: celeryd

**Usage:/etc/init.d/celeryd {start|stop|restart|status}

Configuration file: /etc/default/celeryd

要配置改脚本正常运行worker,你至少需要告诉它在启动时将目录更改到何处(去那儿查找包含应用程序的模块或配置模块)

守护进程脚本通过/etc/default/celeryd文件进行配置。这是一个shell脚本,你可以想下面一样添加环境变量。要添加影响worker的真实的环境变量,还必须export它们(比如:export DISPLAY=":0")


Superuser privileges required:

init-scripts只能被root用户使用,并且shell配置文件也必须属于root用户。

无权限的用户无需使用init-script,他们可以使用celery multi 工具(或者 celery worker --detach

$ celery -A proj multi start worker1 \
    --pidfile="$HOME/run/celery/%n.pid" \
    --logfile="$HOME/log/celery/%n%I.log"

$ celery -A proj multi restart worker1 \
    --logfile="$HOME/log/celery/%n%I.log" \
    --pidfile="$HOME/run/celery/%n.pid

$ celery multi stopwait worker1 --pidfile="$HOME/run/celery/%n.pid"

配置示例

这是给一个Python项目准备的示例配置:

/etc/default/celeryd:

## Names of nodes to start
##   most people will only start one node:
CELERYD_NODES="worker1"
##   but you can also start multiple and configure settings
##   for each in CELERYD_OPTS
##CELERYD_NODES="worker1 worker2 worker3"
##   alternatively, you can specify the number of nodes to start:
##CELERYD_NODES=10

## Absolute or relative path to the 'celery' command:
CELERY_BIN="/usr/local/bin/celery"
##CELERY_BIN="/virtualenvs/def/bin/celery"

## App instance to use
## comment out this line if you don't use an app
CELERY_APP="proj"
## or fully qualified:
##CELERY_APP="proj.tasks:app"

## Where to chdir at start.
CELERYD_CHDIR="/opt/Myproject/"

## Extra command-line arguments to the worker
CELERYD_OPTS="--time-limit=300 --concurrency=8"
## Configure node-specific settings by appending node name to arguments:
##CELERYD_OPTS="--time-limit=300 -c 8 -c:worker2 4 -c:worker3 2 -Ofair:worker1"

## Set logging level to DEBUG
##CELERYD_LOG_LEVEL="DEBUG"

## %n will be replaced with the first part of the nodename.
CELERYD_LOG_FILE="/var/log/celery/%n%I.log"
CELERYD_PID_FILE="/var/run/celery/%n.pid"

## Workers should run as an unprivileged user.
##   You need to create this user manually (or you can choose
##   a user/group combination that already exists (e.g., nobody).
CELERYD_USER="celery"
CELERYD_GROUP="celery"

## If enabled pid and log directories will be created if missing,
## and owned by the userid/group configured.
CELERY_CREATE_DIRS=1

Using a login shell

你可以使用登录的shell继承CELERYD_USER的环境:

You can inherit the environment of the CELERYD_USER by using a login shell:

CELERYD_SU_ARGS="-l"

请注意,不建议使用此选项,并且您应该仅在绝对必要时使用此选项。

PS:有兴趣的可以自己试试,由于没有详细解释,没看懂要说什么。我懒得实验

Django配置示例

Django users now uses the exact same template as above, but make sure that the module that defines your Celery app instance also sets a default value for DJANGO_SETTINGS_MODULE`` as shown in the example Django project in First steps with Django.

可用选项

  • CELERY_APP

    要使用的APP实例(--appopen in new window参数的值)

  • CELERY_BIN

    Celery程序的绝对路径。比如:

    • celery
    • /usr/local/bin/celery
    • /virtualenvs/proj/bin/celery
    • /virtualenvs/proj/bin/python -m celery
  • CELERYD_NODES

    要启动的节点名称列表(用空格分隔)。

  • CELERYD_OPTS

    worker的命令行附加参数,使用 celery worker --help 查看。它还支持扩展语法 multi 配置各个节点的设置。通过 celery multi –help 查看一些multi-node配置示例。

  • CELERYD_CHDIR

    简单理解为工作目录,默认是当前目录。

  • CELERYD_PID_FILE

    PID文件的完整路径,默认是/var/run/celery/%n.pid

  • CELERYD_LOG_FILE

    worker的日志文件的完整路径。默认是 /var/log/celery/%n%I.log Note : 使用 %I 是很重要的当使用了prefork pool的时候,因为让多个进程共享同一个日志文件将导致争用情况。

  • CELERYD_LOG_LEVEL

    日志等级,默认是INFO

  • CELERYD_USER

    运行worker的用户,默认是当前用户

  • CELERYD_GROUP

    运行worker的组,默认是当前组

  • CELERY_CREATE_DIRS

    总是创建目录(日志目录及PID文件目录)。默认是仅在未设置自定义 logfile/pidfile 时创建。

  • CELERY_CREATE_RUNDIR

    总是创建pidfile目录。默认情况下,仅在未设置自定义pidfile位置时启用。

  • CELERY_CREATE_LOGDIR

    总是创建日志文件目录。默认情况下,仅在未设置自定义日志文件位置时启用。

Init-script:celerybeat

**Usage:/etc/init.d/celerybeat {start|stop|restart}

Configuration file/etc/default/celerybeat or /etc/default/celeryd.

示例配置

这是给一个Python项目准备的示例配置:

/etc/default/celerybeat

## Absolute or relative path to the 'celery' command:
CELERY_BIN="/usr/local/bin/celery"
##CELERY_BIN="/virtualenvs/def/bin/celery"

## App instance to use
## comment out this line if you don't use an app
CELERY_APP="proj"
## or fully qualified:
##CELERY_APP="proj.tasks:app"

## Where to chdir at start.
CELERYBEAT_CHDIR="/opt/Myproject/"

## Extra arguments to celerybeat
CELERYBEAT_OPTS="--schedule=/var/run/celery/celerybeat-schedule"

Django示例配置

You should use the same template as above, but make sure the DJANGO_SETTINGS_MODULE variable is set (and exported), and that CELERYD_CHDIR is set to the projects directory:

export DJANGO_SETTINGS_MODULE="settings"

CELERYD_CHDIR="/opt/MyProject"

可用选项

  • CELERY_APP

    要使用的APP实例(--appopen in new window参数的值)

  • CELERYBEAT_OPTS

    celery beat 的额外参数,使用 celery beat --help查看可用的选项列表

  • CELERYBEAT_PID_FILE

    PID文件的完整路径,默认是/var/run/celeryd.pid

  • CELERYBEAT_LOG_FILE

    日志文件的完整路径,默认是/var/log/celeryd.log

  • CELETYBEAT_LOG_LEVEL

    日志等级,默认是INFO

  • CELERYBEAT_USER

    运行beat的用户,默认是当前用户

  • CELERYBEAT_GROUP

    运行beat的组,默认是当前组

  • CELERY_CREATE_DIRS

    总是创建目录(日志目录及PID文件目录)。默认是仅在未设置自定义 logfile/pidfile 时创建。

  • CELERY_CREATE_RUNDIR

    总是创建pidfile目录。默认情况下,仅在未设置自定义pidfile位置时启用。

  • CELERY_CREATE_LOGDIR

    总是创建日志文件目录。默认情况下,仅在未设置自定义日志文件位置时启用。

故障排除

如果init-scripts无法正常工作,可以尝试使用调试模式:

## sh -x /etc/init.d/celeryd start

这可以显示有关服务无法启动的原因的提示。

如果worker启动显示"OK",但很快退出并且没有日志输出,那么可能有一个错误,但是由于守护进程的标准输出已经关闭,您将无法在任何地方看到它们。在这种情况下,可以使用C_FAKEFORK环境变量跳过后台进程化步骤

## C_FAKEFORK=1 sh -x /etc/init.d/celeryd start

现在您应该能够看到错误了。

通常,此类错误是由于权限导致。或者语法错误、拼写错误之类的。当然,如果发现了BUG可以在这里open in new window提交

Usage systemd

Usagesystemctl {start|stop|restart|status} celery.service

Configuration file: /etc/conf.d/celery

Service file: celery.service

这是一个systemd文件的示例:

/etc/systemd/system/celery.service:

[Unit]
Description=Celery Service
After=network.target

[Service]
Type=forking
User=celery
Group=celery
EnvironmentFile=/etc/conf.d/celery
WorkingDirectory=/opt/celery
ExecStart=/bin/sh -c '${CELERY_BIN} -A $CELERY_APP multi start $CELERYD_NODES \
    --pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} \
    --loglevel="${CELERYD_LOG_LEVEL}" $CELERYD_OPTS'
ExecStop=/bin/sh -c '${CELERY_BIN} multi stopwait $CELERYD_NODES \
    --pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} \
    --loglevel="${CELERYD_LOG_LEVEL}"'
ExecReload=/bin/sh -c '${CELERY_BIN} -A $CELERY_APP multi restart $CELERYD_NODES \
    --pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} \
    --loglevel="${CELERYD_LOG_LEVEL}" $CELERYD_OPTS'
Restart=always

[Install]
WantedBy=multi-user.target

当你将文件放入/etc/systemd/system时,记得执行systemctl daemon-reload,每次更改之后也应该执行。使用systemctl enable celery.service命令开启开机自启。

可以指定额外的依赖关系,比如你使用RabbitMQ作为broker,则应该在[Unit]段指定AfterRequires等于rabbitmq-server.service。See:systemdopen in new window

要设置user、group、chdir的话,在/etc/systemd/system/celery.service文件中使用UserGroup以及WorkingDirectory进行配置。

或者也可以使用systemd-tmpfiles来创建工作目录(for logs and pid)

file: /etc/tmpfiles.d/celery.conf

d /run/celery 0755 celery celery -
d /var/log/celery 0755 celery celery -

示例配置

这是给一个Python项目准备的示例配置:

/etc/conf.d/:

## Name of nodes to start
## here we have a single node
CELERYD_NODES="w1"
## or we could have three nodes:
##CELERYD_NODES="w1 w2 w3"

## Absolute or relative path to the 'celery' command:
CELERY_BIN="/usr/local/bin/celery"
##CELERY_BIN="/virtualenvs/def/bin/celery"

## App instance to use
## comment out this line if you don't use an app
CELERY_APP="proj"
## or fully qualified:
##CELERY_APP="proj.tasks:app"

## How to call manage.py
CELERYD_MULTI="multi"

## Extra command-line arguments to the worker
CELERYD_OPTS="--time-limit=300 --concurrency=8"

## - %n will be replaced with the first part of the nodename.
## - %I will be replaced with the current child process index
##   and is important when using the prefork pool to avoid race conditions.
CELERYD_PID_FILE="/var/run/celery/%n.pid"
CELERYD_LOG_FILE="/var/log/celery/%n%I.log"
CELERYD_LOG_LEVEL="INFO"

## you may wish to add these options for Celery Beat
CELERYBEAT_PID_FILE="/var/run/celery/beat.pid"
CELERYBEAT_LOG_FILE="/var/log/celery/beat.log"

Service file: celerybeat.service

这是Celery Beat的示例systemd文件:

/etc/systemd/system/celerybeat.service

[Unit]
Description=Celery Beat Service
After=network.target

[Service]
Type=simple
User=celery
Group=celery
EnvironmentFile=/etc/conf.d/celery
WorkingDirectory=/opt/celery
ExecStart=/bin/sh -c '${CELERY_BIN} -A ${CELERY_APP} beat  \
    --pidfile=${CELERYBEAT_PID_FILE} \
    --logfile=${CELERYBEAT_LOG_FILE} --loglevel=${CELERYD_LOG_LEVEL}'
Restart=always

[Install]
WantedBy=multi-user.target

当你将文件放入/etc/systemd/system时,记得执行systemctl daemon-reload,每次更改之后也应该执行。使用systemctl enable celery.service命令开启开机自启。

以Root权限运行worker

以Root运行很危险,默认情况下会闪退。如果执意如此,需要使用C_FORCE_ROOT

Running the worker with superuser privileges is a very dangerous practice. There should always be a workaround to avoid running as root. Celery may run arbitrary code in messages serialized with pickle - this is dangerous, especially when run as root.

By default Celery won’t run workers as root. The associated error message may not be visible in the logs but may be seen if C_FAKEFORK is used.

To force Celery to run workers as root use C_FORCE_ROOT.

When running as root without C_FORCE_ROOT the worker will appear to start with “OK” but exit immediately after with no apparent errors. This problem may appear when running the project in a new development or production environment (inadvertently) as root.

supervisor

launchd (macOS)