repositorio proyecto compartir actualizar django nginx reload gunicorn upstart

compartir - Una mejor forma de reiniciar/recargar Gunicorn(a través de Upstart) después de ''git pull''ing mis proyectos de Django



actualizar repositorio github (5)

Estoy buscando algo mejor que sudo restart projectname cada vez que sudo restart projectname un git pull origin master , que saca mis últimos cambios a un proyecto de Django. Este comando de restart , creo, está relacionado con Upstart, que utilizo para iniciar / finalizar mi proceso de servidor de Gunicorn.

Este reinicio provoca una breve interrupción. Los usuarios que accedan al servidor web (nginx) recibirán 500, porque Gunicorn todavía está reiniciando. De hecho, parece reiniciarse instantáneamente, pero la página tarda unos segundos en cargarse.

¿Alguna idea sobre cómo hacer esto sin interrupciones? Idealmente, me gustaría emitir mi git pull y las recargas de Gunicorn automáticamente.


Systemd, gunicornio y Ubuntu

Aquí está el one-liner, si está ejecutando su servicio de gunicorn con systemd .

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

Detalles paso a paso

Dado que el FAQ dice que la forma correcta de volver a cargar correctamente a los trabajadores es usando kill -HUP <Main PID> , donde <Main PID> es la identificación del proceso maestro, extraemos el PID maestro usando systemctl, y ejecuta kill -HUP <Main PID> .

1) Obtenga información sobre el proceso desde systemd utilizando el nombre del servicio

systemctl status gunicorn

donde gunicorn es el nombre del servicio, ubicado en /etc/systemd/system/ .

Ejemplo de salida:

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) Obtener el ID de proceso (PID) del proceso principal de Armeria

El comando sed funciona de la siguiente manera: sed ''s/<search this>/<replace with this>/g''

  • s significa para el comando sustitutivo , y g significa que busca toda la entrada globalmente .
  • La -n indica a sed que no imprima todas las líneas (o, de hecho, que no imprima nada).
  • La p al final le dice a sed que imprima la línea correspondiente .
  • Buscamos .*Main PID: /(.*/)$ , Que es un patrón de expresión regular, que tiene las siguientes partes:. .* Coincide con cualquier carácter ( . ) Cero o más veces ( * ). Luego buscamos Main PID: seguido de cualquier carácter, repetido cero o más veces ( .* ). Para capturar todos los caracteres después del Main PID: -text, incluimos .* Entre paréntesis, que se escapan con barras diagonales inversas: /(.*/) . $ indica el final de línea.
  • La parte "reemplazar con esto" del comando sed es simplemente /1 , lo que significa el primer conjunto de caracteres capturados.

Ejemplo de salida:

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

3) Deshacerse de los personajes adicionales

Pipe la salida para cut . El cut -f1 -d'' '' significa que

  • La cadena está delimitada por espacios: Aquí -d determina el delimitador, que es el caracter justo después de la -d . Como el delimitador es espacio, lo incluimos entre comillas.
  • -f significa que el corte se realiza utilizando el delimitador (y no por bytes), y -f1 significa que queremos extraer el primer elemento de la lista.

Ejemplo de salida:

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

4) Usa el PID principal

La canalización a xargs significa simplemente ejecutar el comando con argumentos de la tubería en el lado izquierdo. Como estamos conectando solo el PID principal a xargs,

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

es básicamente lo mismo que

echo <Main PID > | xargs kill -HUP

que se traduce en

kill -HUP <Main PID >

Editar

Una solución un poco más sólida sería usar cut -f1 -d$''/n'' o grep -m1 "" delante de cut -f1 -d'' '' , para seleccionar solo la primera línea del partido. No puedo imaginar ninguna circunstancia, donde habría dos coincidencias para el Main PID: sin embargo.


Ejecutamos Gunicorn bajo Supervisor, pero esta es la forma más simple y limpia que hemos encontrado para recargar graciosamente Gunicorn cuando se confunde:

sudo pkill -HUP -f gunicorn.*master


Para aquellos que no usan supervisord: lo que Rob dijo, también funciona con ps,

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


Para una recarga elegante, en su lugar debe usar el comando de reload de Upstart, por ejemplo:

sudo reload jobname

De acuerdo con la página de manual initctl (Upstart), reload enviará una señal HUP al proceso:

reload JOB [KEY=VALUE]... Sends the SIGHUP signal to running process of the named JOB instance.

... que para Gunicorn desencadenará un reinicio elegante (ver FAQ ).


Puedes decirle a Gunicorn que recargue con gracia usando la señal HUP así:

kill -HUP <pid>

(ver las FAQ para más detalles)

Utilizo Supervisor para controlar mi servidor de Gunicorn, lo que me permite usar esta forma (ligeramente hacky) de volver a cargar Gunicorn después de una implementación:

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

Obviamente podrías lograr algo similar con pidof o ps .

En realidad, se ejecuta desde un script Fabric , por lo que ni siquiera tengo que iniciar sesión en el servidor.