我有一个使用 Nginx 和 Gunicorn 的 Django 应用程序“djngxgun”。我刚刚安装了 Supervisor,以便可以使用它来管理我的 Gunicorn 进程。问题是,在我重新启动服务器后,Supervisor 不会启动 Gunicorn。当我通过 Supervisor 启动 Gunicorn(“sudo Supervisorctl start djngxgun”)时,我看到我的 Gunicorn error.log 文件中重复出现以下错误:
2014-02-28 15:36:47 [4753] [INFO] Starting gunicorn 18.0
Traceback (most recent call last):
File "/home/djngxgun/venv/djngxgun/bin/gunicorn", line 9, in <module>
load_entry_point('gunicorn==18.0', 'console_scripts', 'gunicorn')()
File "/home/djngxgun/venv/djngxgun/local/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py", line 71, in run
WSGIApplication("%(prog)s [OPTIONS] [APP_MODULE]").run()
File "/home/djngxgun/venv/djngxgun/local/lib/python2.7/site-packages/gunicorn/app/base.py", line 143, in run
Arbiter(self).run()
File "/home/djngxgun/venv/djngxgun/local/lib/python2.7/site-packages/gunicorn/arbiter.py", line 172, in run
self.start()
File "/home/djngxgun/venv/djngxgun/local/lib/python2.7/site-packages/gunicorn/arbiter.py", line 124, in start
self.pidfile.create(self.pid)
File "/home/djngxgun/venv/djngxgun/local/lib/python2.7/site-packages/gunicorn/pidfile.py", line 38, in create
fd, fname = tempfile.mkstemp(dir=fdir)
File "/usr/lib/python2.7/tempfile.py", line 300, in mkstemp
return _mkstemp_inner(dir, prefix, suffix, flags)
File "/usr/lib/python2.7/tempfile.py", line 235, in _mkstemp_inner
fd = _os.open(file, flags, 0600)
OSError: [Errno 13] Permission denied: '/var/run/tmpcda84p'
问题似乎在于 djngxgun 帐户需要在 /var/run 中创建一个临时文件,但该目录的权限阻止了它:
drwxr-xr-x 14 root root 640 Feb 28 15:36 /run
如果我手动更改 /run(/var/run 是 /run 的符号链接),使其组所有者为“adm”,并且它是组可写的,并且 djngxgun 被添加到 adm 组,如下所示,
drwxrwxr-x 14 root adm 640 Feb 28 15:36 /run
... 我可以通过 Supervisor 启动 Gunicorn,没有任何问题。但是,如果我重新启动服务器,组所有权和权限将恢复为原始设置,这会导致错误再次发生。正如您所料,如果我只是手动运行启动脚本(“sudo /www/djngxgun/bin/start-gunicorn &”),Gunicorn 就可以毫无问题地启动。
我是否错误地配置了 Gunicorn 和/或 Supervisor?如果我使用 Supervisor,我不知道如何避免需要写入 /var/run,但如果它由 root 拥有,我就无法做到。我不认为我想通过 root 用户运行我的应用程序。我没有看到任何可以解决此问题的 Gunicorn 或 Supervisor 设置。还有其他方法吗?
谢谢。
这是我的 Gunicorn 启动脚本:
#!/bin/bash
NAME=djngxgun
DJANGODIR=/www/djngxgun
USER=$NAME
GROUP=$NAME
NUM_WORKERS=3
DJANGO_SETTINGS_MODULE=conf.prod
DJANGO_WSGI_MODULE=conf.wsgi
WORKON_HOME=/home/${USER}/venv
source `which virtualenvwrapper.sh`
workon $NAME
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DJANGODIR:$PYTHONPATH
echo "Starting $NAME as `whoami`"
exec gunicorn $DJANGO_WSGI_MODULE:application \
--name $NAME \
--workers $NUM_WORKERS \
--user=$USER \
--group=$GROUP \
--bind=127.0.0.1:8000 \
--pid /var/run/gunicorn.pid \
--access-logfile /var/log/gunicorn/access.log \
--error-logfile /var/log/gunicorn/error.log \
--log-level=debug
这是我的 Supervisor 配置文件“/etc/supervisor/conf.d/djngxgun.conf”
[program:djngxgun]
command = /www/djngxgun/bin/start-gunicorn
user=djngxgun
stdout_logfile = /var/log/gunicorn/supervisor.log
redirect_stderr = true
答案1
您不应该以 root 身份运行您的 gunicorn 服务器,试想一下,如果有人在您的代码中发现漏洞,就可以对服务器做任何事情。
将 pidfile 放在 /tmp 或 /var/tmp 中并以非特权用户身份运行。
答案2
我找到了解决办法。解决方案是在项目的 Supervisor 配置文件中设置“user = root”。文档说,“如果supervisord以root身份运行,则此UNIX用户帐户将用作运行该程序的帐户。” 因此,以这种方式设置用户相当于我使用“sudo”手动运行脚本。