我在Debian 7.8上运行了一个Django 1.62应用程序,其中Nginx 1.2.1作为我的代理服务器,Gunicorn 19.1.1作为我的应用程序服务器。我已经安装了Celery 3.1.7和RabbitMQ 2.8.4来处理异步任务。我正在尝试使用Supervisor 3.0a8来管理我的各种应用程序,尤其是Celery。问题是,当我尝试通过Supervisor启动Celery时,我收到此错误:
ImproperlyConfigured: The SECRET_KEY setting must not be empty.
(我在底部显示整个堆栈跟踪。)
我的所有配置文件都保存在" conf"位于我的" myproj"正下方的目录像这样的项目目录:
conf
├── celeryconfig.py
├── celeryconfig.pyc
├── celery.py
├── __init__.py
├── middleware.py
├── settings
│ ├── base.py
│ ├── dev.py
│ ├── __init__.py
│ ├── prod.py
├── urls.py
├── wsgi.py
我的生产Django设置保存在prod.py设置文件中,该文件继承了我的base.py基本设置。我将密钥保存在我的虚拟环境的postactivate文件中,然后将其读入我的生产设置,如下所示。我已经通过Python解释器验证了密钥存在于我的生产设置中。
# conf/settings/prod.py
from conf.settings.base import *
...
# get_env_variable is defined in base.py
SECRET_KEY = get_env_variable("SECRET_KEY")
这是get_env_variable函数,它在以下位置读取密钥:
# conf/settings/base.py
def get_env_variable(var_name):
try:
return os.environ[var_name]
except KeyError:
error_msg = "Set the %s environment variable" % var_name
raise ImproperlyConfigured(error_msg)
这是我的Supervisor配置文件。它基于Celery documentation中显示的示例文件:
# /etc/supervisor/conf.d/myproj.conf
[program:myproj]
command = /www/myproj/bin/start-gunicorn
user = root
stdout_logfile = /var/log/gunicorn/supervisor.log
redirect_stderr = true
[program:celery]
directory=/www/myproj
command=/home/myproj/venv/myproj/bin/celery worker --app=conf -l debug
user=nobody
numprocs=1
stdout_logfile=/var/log/celery/celery.log
stderr_logfile=/var/log/celery/celery.log
autostart=true
autorestart=true
startsecs=10
stopwaitsecs=600
killasgroup=true
priority=998
以下是我如何使用Supervisor加载新的Celery配置:
sudo service supervisor stop
sudo service supervisor start
这是我的Celery应用程序文件:
# conf/celery.py
from __future__ import absolute_import
import os
from celery import Celery
from django.conf import settings
from conf import celeryconfig
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'conf.settings')
app = Celery('conf')
app.config_from_object(celeryconfig)
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
这是我的Celery配置文件:
# conf/celeryconfig.py
BROKER_URL = 'amqp://guest@localhost:5672//'
CELERY_RESULT_BACKEND = 'amqp'
CELERY_ACCEPT_CONTENT = ['json', ]
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TASK_RESULT_EXPIRES = 3600
CELERY_SEND_TASK_ERROR_EMAILS = True
根据Celery文档,我修改了__init __。py:
# conf/__init__.py
from __future__ import absolute_import
from .celery import app as celery_app
我可以使用以下命令手动启动Celery,它启动就好了:
workon myproj # Activate project's virtual environment
celery worker -A conf -l info
然而,当我尝试通过Supervisor启动它时,我得到了我所描述的错误。考虑到主管可能无法访问Django密钥,因为它是一个环境变量,我尝试在我的prod.py设置文件中对密钥进行硬编码(而不是通过get_env_variable函数读取)这并没有解决问题。
我尝试将所有设置合并到prod.py设置文件中,该文件包含实际的密钥,但没有帮助。
我也尝试将此环境参数添加到Supervisor配置文件中,如下所示,但这并没有解决问题:
# /etc/supervisor/conf.d/myproj.conf
...
[program:celery]
environment=SECRET_KEY="(my secret key)"
directory=/www/myproj
command=/home/myproj/venv/myproj/bin/celery worker --app=conf -l debug
user=nobody
...
我尝试设置"用户"以我启动网站的用户的名字,但也没有帮助。
# /etc/supervisor/conf.d/myproj.conf
...
[program:celery]
environment=SECRET_KEY="(my secret key)"
directory=/www/myproj
command=/home/myproj/venv/myproj/bin/celery worker --app=conf -l debug
user=myproj
...
我读到了一个名为django-supervisor的库,它可以简化Django和Supervisor之间的集成,但如果我使用该库,我会得到同样的错误。
最后我读了here on SO,如果你的密钥包含"%"标志,主管不喜欢它。我注意到我的钥匙确实包含了一个"%"签署所以我像这样逃脱了#34; %%"但这也没有解决问题。
谁能看到我做错了什么?我在这里遇到过在不同环境下遇到同样错误的用户的其他问题,但我尝试实施所讨论的各种解决方案,但都没有解决问题。
非常感谢您的想法。对于长期的问题感到抱歉,但这个问题有许多可动的部分。
这是整个堆栈跟踪:
Traceback (most recent call last):
File "/home/myproj/venv/myproj/bin/celery", line 11, in <module>
sys.exit(main())
File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/__main__.py", line 30, in main
main()
File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/bin/celery.py", line 81, in main
cmd.execute_from_commandline(argv)
File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/bin/celery.py", line 769, in execute_from_commandline
super(CeleryCommand, self).execute_from_commandline(argv)))
File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/bin/base.py", line 307, in execute_from_commandline
return self.handle_argv(self.prog_name, argv[1:])
File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/bin/celery.py", line 761, in handle_argv
return self.execute(command, argv)
File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/bin/celery.py", line 693, in execute
).run_from_argv(self.prog_name, argv[1:], command=argv[0])
File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/bin/worker.py", line 179, in run_from_argv
return self(*args, **options)
File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/bin/base.py", line 270, in __call__
ret = self.run(*args, **kwargs)
File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/bin/worker.py", line 212, in run
state_db=self.node_format(state_db, hostname), **kwargs
File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/worker/__init__.py", line 95, in __init__
self.app.loader.init_worker()
File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/loaders/base.py", line 128, in init_worker
self.import_default_modules()
File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/loaders/base.py", line 116, in import_default_modules
signals.import_modules.send(sender=self.app)
File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/utils/dispatch/signal.py", line 166, in send
response = receiver(signal=self, sender=sender, **named)
File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/fixups/django.py", line 69, in on_import_modules
self.worker_fixup.validate_models()
File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/kombu/utils/__init__.py", line 322, in __get__
value = obj.__dict__[self.__name__] = self.__get(obj)
File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/fixups/django.py", line 64, in worker_fixup
self._worker_fixup = DjangoWorkerFixup(self.app)
File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/celery/fixups/django.py", line 99, in __init__
self._cache = import_module('django.core.cache')
File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
__import__(name)
File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/django/core/cache/__init__.py", line 69, in <module>
if DEFAULT_CACHE_ALIAS not in settings.CACHES:
File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/django/conf/__init__.py", line 54, in __getattr__
self._setup(name)
File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/django/conf/__init__.py", line 49, in _setup
self._wrapped = Settings(settings_module)
File "/home/myproj/venv/myproj/local/lib/python2.7/site-packages/django/conf/__init__.py", line 151, in __init__
raise ImproperlyConfigured("The SECRET_KEY setting must not be empty.")
django.core.exceptions.ImproperlyConfigured: The SECRET_KEY setting must not be empty.
答案 0 :(得分:1)
在celery配置中,您需要指定正在使用的设置。目前,您使用prod.py
作为生产代码,因此celery.py
应为
# conf/celery.py
from __future__ import absolute_import
import os
from celery import Celery
from django.conf import settings
from conf import celeryconfig
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'conf.settings.prod')
app = Celery('conf')
app.config_from_object(celeryconfig)
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
因此,芹菜会知道您要使用哪个设置文件(如果您在设置文件夹中有多个设置)