Лучший способ перезапустить / перезагрузить Gunicorn (через Upstart) после 'git pull' моих проектов Django - PullRequest
53 голосов
/ 27 марта 2012

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

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

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

Ответы [ 6 ]

81 голосов
/ 27 марта 2012

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

kill -HUP <pid>

(подробности см. В FAQ )

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

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

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

На самом деле он запускается из сценария Fabric , поэтому мне даже не требуется входить на сервер.

25 голосов
/ 11 января 2015

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

ps aux |grep gunicorn |grep projectname | awk '{ print $2 }' |xargs kill -HUP
17 голосов
/ 26 апреля 2013

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

sudo reload jobname

Согласно initctl (Upstart) manpage , reload отправит процессу HUP сигнал:

reload JOB [KEY=VALUE]...

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

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

7 голосов
/ 05 ноября 2017

Systemd, gunicorn & Ubuntu

Это однострочник, если вы используете службу gunicorn с systemd .

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

Подробнеешаг за шагом

Поскольку документация gunicorn говорит о том, что правильный способ корректной перезагрузки рабочих заключается в использовании 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

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

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

Пример вывода:

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

3) Избавьтесь от лишних символов

Передайте вывод в cut .cut -f1 -d' ' означает, что

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

Пример вывода:

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

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

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

 systemctl status gunicorn-django |  sed -n 's/.*Main PID: \(.*\)$/\1/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:, хотя.

2 голосов
/ 24 октября 2018

Возможно, это не прямой ответ на вопрос, но для тех, кто просто ищет способ перезапустить gunicorn веб-сервер, вы можете использовать killall gunicorn и затем выполнить команду, чтобы снова запустить gunicorn. Например:

killall gunicorn
gunicorn --bind 0.0.0.0:80 --reload app:app

Примечание: killall gunicorn немедленно прекратит все процессы, связанные с оружием, поэтому убедитесь, что вы понимаете, что делаете.

2 голосов
/ 29 октября 2015

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

sudo pkill -HUP -f gunicorn.*master
...