Лучший способ перезапустить / перезагрузить Gunicorn (через Upstart) после "git pull" мои проекты Django

Я ищу что-то лучше, чем sudo restart projectname каждый раз, когда я выпустить git pull origin master, который снимает мои последние изменения в проекте Django. Это restart команда, я считаю, связана с выскочкой,которую я использую для запуска / запуска моего процесса сервера Gunicorn.

этот перезапуск вызывает короткое отключение. Пользователи, попадающие на веб-сервер (nginx), получат 500, потому что Gunicorn все еще перезапускается. На самом деле, кажется, что он перезапускается мгновенно, но для страниц требуется несколько секунд нагрузка.

любые идеи о том, как сделать это бесшовное? В идеале, я хотел бы выпустить мой git pull и Gunicorn перезагружается автоматически.

5 ответов


для изящной перезагрузки вы должны вместо этого использовать Upstart's , например:

sudo reload jobname

согласно initctl (выскочка) manpage, reload отправить HUP сигнал к процессу:

reload JOB [KEY=VALUE]...

       Sends the SIGHUP signal to running process of the named JOB instance.

...что для Gunicorn вызовет изящный перезапуск (см. часто задаваемые вопросы).


вы можете сказать Gunicorn перезагрузить изящно, используя HUP сигнал вот так:

kill -HUP <pid>

(см. часто задаваемые вопросы дополнительные сведения)

я использую руководитель для управления моим сервером Gunicorn, который позволяет мне использовать этот (слегка хакерский) способ перезагрузки Gunicorn после развертывания:

supervisorctl status gunicorn | sed "s/.*[pid ]\([0-9]\+\)\,.*//" | xargs kill -HUP

вы, очевидно, могли бы добиться чего-то подобного с pidof или ps.

Это на самом деле бегут от ткани сценарий, поэтому мне даже не нужно входить на сервер вообще.


для тех, кто не использует supervisord: что сказал Роб, он также работает с ps,

ps aux |grep gunicorn |grep projectname | awk '{ print  }' |xargs kill -HUP

Systemd, gunicorn & Ubuntu

здесь ОДН-вкладыш, если вы бежите ваше обслуживание gunicorn с systemd в.

systemctl status gunicorn |  sed -n 's/.*Main PID: \(.*\)$//g p' | cut -f1 -d' ' | xargs kill -HUP

детали шаг за шагом

С gunicorn docs скажите, что правильный способ изящно перезагрузить рабочих-использовать kill -HUP <Main PID>, где <Main PID> это идентификатор процесса главного процесса, мы извлекаем главный PID с помощью systemctl и запускаем kill -HUP <Main PID>.

1) Сделать информация о процессе из systemd с использованием имени сервиса

systemctl status gunicorn 

здесь gunicorn - название сервиса, расположенного по адресу /etc/systemd/system/.

пример:

ubuntu@ip-10-4-12-247:~$ systemctl status gunicorn
● gunicorn.service - Gunicorn server for yourproject.com
   Loaded: loaded (/etc/systemd/system/gunicorn.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2017-11-04 19:16:24 UTC; 1h 15min ago
 Main PID: 10673 (gunicorn)
   CGroup: /system.slice/gunicorn.service
           ├─10673 /home/ubuntu/site/venv/bin/python3 /home/ubuntu/site/venv/bin/gunicorn --workers 3 --bind unix:/tmp/yourproject.socket config.wsgi:application
           ├─11069 /home/ubuntu/site/venv/bin/python3 /home/ubuntu/site/venv/bin/gunicorn --workers 3 --bind unix:/tmp/yourproject.socket config.wsgi:application
           ├─11070 /home/ubuntu/site/venv/bin/python3 /home/ubuntu/site/venv/bin/gunicorn --workers 3 --bind unix:/tmp/yourproject.socket config.wsgi:application
           └─11071 /home/ubuntu/site/venv/bin/python3 /home/ubuntu/site/venv/bin/gunicorn --workers 3 --bind unix:/tmp/yourproject.socket config.wsgi:application

Nov 04 20:27:04 ip-10-4-12-247 gunicorn[10673]: [2017-11-04 20:27:04 +0000] [11047] [INFO] Booting worker with pid: 11047
Nov 04 20:27:04 ip-10-4-12-247 gunicorn[10673]: [2017-11-04 20:27:04 +0000] [11048] [INFO] Booting worker with pid: 11048
Nov 04 20:32:16 ip-10-4-12-247 gunicorn[10673]: [2017-11-04 20:32:16 +0000] [10673] [INFO] Handling signal: hup
Nov 04 20:32:16 ip-10-4-12-247 gunicorn[10673]: [2017-11-04 20:32:16 +0000] [10673] [INFO] Hang up: Master
Nov 04 20:32:16 ip-10-4-12-247 gunicorn[10673]: [2017-11-04 20:32:16 +0000] [11046] [INFO] Worker exiting (pid: 11046)
Nov 04 20:32:16 ip-10-4-12-247 gunicorn[10673]: [2017-11-04 20:32:16 +0000] [11047] [INFO] Worker exiting (pid: 11047)
Nov 04 20:32:16 ip-10-4-12-247 gunicorn[10673]: [2017-11-04 20:32:16 +0000] [11048] [INFO] Worker exiting (pid: 11048)
Nov 04 20:32:16 ip-10-4-12-247 gunicorn[10673]: [2017-11-04 20:32:16 +0000] [11069] [INFO] Booting worker with pid: 11069
Nov 04 20:32:16 ip-10-4-12-247 gunicorn[10673]: [2017-11-04 20:32:16 +0000] [11070] [INFO] Booting worker with pid: 11070
Nov 04 20:32:16 ip-10-4-12-247 gunicorn[10673]: [2017-11-04 20:32:16 +0000] [11071] [INFO] Booting worker with pid: 11071

2) Получить идентификатор процесса (PID) основного процесса gunicorn

на sed команда работает следующим образом:sed 's/<search this>/<replace with this>/g'

  • s средством заменить и g означает что поиск весь вход .
  • на -n флаг сообщает sed не печатать каждую строку (или на самом деле ничего не печатать.)
  • на p в конце говорит sed для печать совпадающей строки.
  • мы ищем .*Main PID: \(.*\)$, который является шаблоном регулярного выражения, который имеет следующие части:.* соответствует любому символу (.) ноль или более раз (*). Тогда мы ищем Main PID: за ними следуют любые символы, повторяемые ноль или более раз (.*). Чтобы захватить все символы после Main PID:-текст, прилагаем .* в скобки, которые экранируются с обратными косыми чертами:\(.*\). $ обозначает конец строки.
  • " заменить на это " часть команды sed просто , что означает первый захваченный набор символов.

пример:

ubuntu@ip-10-4-12-247:~$ systemctl status gunicorn |  sed -n 's/.*Main PID: \(.*\)$//g p'
10673 (gunicorn)

3) избавиться от лишних персонажи

Pipe выход к вырезать. The cut -f1 -d' ' означает, что

  • строка разделена пробелом: здесь -d определяет разделитель, который является символом сразу после -d. Поскольку разделителем является пробел, мы заключаем это в кавычки.
  • -f означает только то, что резка производится с помощью разделителя (а не байтов), и -f1 означает, что мы хотим вынуть первый элемент список.

пример:

ubuntu@ip-10-4-12-247:~$ systemctl status gunicorn |  sed -n 's/.*Main PID: \(.*\)$//g p' | cut -f1 -d' '
10673

4) Используйте основной PID

трубопровод xargs означает просто выполнение команды с аргументами из трубы с левой стороны. Поскольку мы передаем только основной PID в xargs,

 systemctl status gunicorn-django |  sed -n 's/.*Main PID: \(.*\)$//g p' | cut -f1 -d' ' | xargs kill -HUP

в основном то же самое как

echo <Main PID > | xargs kill -HUP

что означает

kill -HUP <Main PID >

Edit

немного более надежное решение было бы использовать cut -f1 -d$'\n' или grep -m1 "" перед cut -f1 -d' ', чтобы выбрать только первую строку матч. Я не могу понять никаких обстоятельств, где было бы два матча для Main PID:, хотя.


мы запускаем Gunicorn под надзором, но это самый простой и чистый способ, который мы нашли, чтобы изящно перезагрузить Gunicorn, когда он запутывается:

sudo pkill -HUP -f gunicorn.*master