У меня есть сервер разработки, на котором запущен gunicorn / Django за nginx. В рамках более широкого обновления серверной среды я попытался обновить Gunicorn с 18.0 до 19.2.1, но служба больше не запускалась. (На сервере работает Arch и поэтому используется systemctl.)
Конфигурация Gunicorn была сделана кем-то, кто больше не находится в нашем распоряжении и не очень хорошо знал Gunicorn, я не смог исправить или даже определить местонахождение проблемы, поэтому я вернулся к версии 18.0, и на данный момент она работает. Однако я хотел бы в конечном итоге обновить его и привести конфигурацию в такую форму, в которой он будет работать. У меня такое ощущение, что текущая конфигурация неоптимальна или избыточна, но я не могу знать наверняка :-).
Ничего не изменилось в окружении (или виртуальном уровне, в котором работает Gunicorn), был улучшен только сам Gunicorn. Systemctl произвел эту ошибку на systemctl start gunicorn
:
● gunicorn.service - gunicorn daemon (production)
Loaded: loaded (/usr/lib/systemd/system/gunicorn.service; enabled)
Active: failed (Result: resources) since Tue 2015-02-17 20:55:41 UTC; 8s ago
Process: 2837 ExecStop=/bin/kill -s QUIT $MAINPID (code=exited, status=0/SUCCESS)
Process: 9608 ExecReload=/bin/kill -s HUP $MAINPID (code=exited, status=0/SUCCESS)
Process: 5353 ExecStart=/home/django/gunicorn/run.sh (code=exited, status=0/SUCCESS)
Main PID: 24876 (code=exited, status=0/SUCCESS)
Feb 17 20:55:41 ashima systemd[1]: PID file /home/django/gunicorn/gunicorn.pid not readable (yet?) after start.
Feb 17 20:55:41 ashima systemd[1]: gunicorn.service never wrote its PID file. Failing.
Feb 17 20:55:41 ashima systemd[1]: Failed to start gunicorn daemon (production).
Feb 17 20:55:41 ashima systemd[1]: Unit gunicorn.service entered failed state.
Попытка запустить команду gunicorn, содержащуюся в run.sh
(вставлено ниже) вручную из оболочки, он просто немедленно вышел без каких-либо ошибок, с кодом выхода 0. Ничего не было зарегистрировано. Фактически, похоже, что мой предшественник отключил ведение журнала Gunicorn некоторое время назад после того, как файл журнала вырос до тревожного размера, но это проблема на другой день.
Вот содержимое соответствующих файлов:
/usr/lib/systemd/system/gunicorn.service:
[Unit]
Description=gunicorn daemon
[Service]
Type=forking
PIDFile=/home/django/gunicorn/gunicorn.pid
User=django
WorkingDirectory=/home/django/[name_withheld]/project
ExecStart=/home/django/gunicorn/run.sh
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=false
[Install]
WantedBy=multi-user.target
/home/django/gunicorn/run.sh:
#!/bin/bash
set -e
cd /home/django/[name_withheld]/project
source /home/django/.venv/bin/activate
exec gunicorn -p /home/django/gunicorn/gunicorn.pid -c /home/django/gunicorn/config.py -e HTTPS=on [name_withheld]_site.wsgi:application
/home/django/gunicorn/config.py:
bind = 'unix:/tmp/gunicorn.sock'
backlog = 2048
workers = 16
worker_class = 'egg:gunicorn#sync'
worker_connections = 1000
timeout = 30
keepalive = 2
debug = False
spew = False
daemon = True
pidfile = None
umask = 0755
user = None
group = None
tmp_upload_dir = None
raw_env = 'HTTPS=on'
errorlog = '-'
loglevel = 'info'
accesslog = None
proc_name = None
def post_fork(server, worker):
server.log.info("Worker spawned (pid: %s)", worker.pid)
def pre_fork(server, worker):
pass
def pre_exec(server):
server.log.info("Forked child, re-executing.")
def when_ready(server):
server.log.info("Server is ready. Spawning workers")
(Из комментариев, отправленных к вопросу, я должен особо отметить комментарий скарап, так как это помогло мне найти решение самостоятельно, сделав ошибки правильного вывода Gunicorn. Хотел бы я наградить за это частичное вознаграждение; преобразование этого комментария в ответ еще не было бы полным ответом, но существенно помогло.)
Оказывается, это была проблемная строка в файле конфигурации:
worker_class = 'egg:gunicorn#sync'
Это вызвало эту ошибку:
Error: class uri 'egg:gunicorn#sync' invalid or not found:
[Traceback (most recent call last):
File "/home/django/.venv/lib/python2.7/site-packages/gunicorn/util.py", line 113, in load_class
return pkg_resources.load_entry_point(dist, section, name)
File "/home/django/.venv/lib/python2.7/site-packages/setuptools-0.6c11-py2.7.egg/pkg_resources.py", line 318, in load_entry_point
return get_distribution(dist).load_entry_point(group, name)
File "/home/django/.venv/lib/python2.7/site-packages/setuptools-0.6c11-py2.7.egg/pkg_resources.py", line 2220, in load_entry_point
raise ImportError("Entry point %r not found" % ((group,name),))
ImportError: Entry point ('gunicorn.workers', 'sync') not found
]
Заменив его на worker_class = 'sync'
исправлена ошибка ImportError и, следовательно, проблема. Никаких других изменений конфигурации при обновлении 18.0 -> 19.2.1 не потребовалось.
Похоже, есть проблема с документацией Gunicorn, о которой я намерен сообщить, потому что на момент написания этой статьи документация для v19.2.1 по-прежнему заявляю, что egg:gunicorn#[worker]
синтаксис правильный. (В этом примере используется gevent, но похоже, что он должен применяться к другим типам). Кто знает, это может быть действительным в некоторых обстоятельствах, но в моем (gunicorn в virtualenv, установленном с помощью pip) это не так.