code

내 Django 프로젝트를 'git pull'한 후 Gunicorn을 다시 시작 / 다시로드하는 더 좋은 방법 (Upstart를 통해)

codestyles 2021. 1. 10. 17:16
반응형

내 Django 프로젝트를 'git pull'한 후 Gunicorn을 다시 시작 / 다시로드하는 더 좋은 방법 (Upstart를 통해)


장고 프로젝트에 대한 최신 변경 사항을 가져 오는를 sudo restart projectname발행 할 때마다 더 나은 것을 찾고 git pull origin master있습니다. restart명령은 Gunicorn 서버 프로세스를 시작 / 정상하는 데 사용하는 Upstart와 관련이 있다고 생각합니다.

다시 시작하면 잠시 중단됩니다. 웹 서버 (nginx)에 접속하는 사용자는 Gunicorn이 여전히 다시 시작되기 때문에 500을 받게됩니다. 실제로는 즉시 다시 시작되는 것처럼 보이지만 페이지를로드하는 데 몇 초가 걸립니다.

이를 원활하게 만드는 방법에 대한 아이디어가 있습니까? 이상적으로는 내 git pull및 Gunicorn 리로드를 자동으로 발행하고 싶습니다 .


정상적으로 다시로드하려면 대신 Upstart의 reload명령 을 사용해야합니다 . 예 :

sudo reload jobname

initctl (무례한)에 따르면, , reload송신 할 HUP프로세스로 신호 :

reload JOB [KEY=VALUE]...

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

... Gunicorn의 경우 정상적으로 다시 시작됩니다 ( FAQ 참조 ).


Gunicorn에게 HUP다음과 같은 신호를 사용하여 정상적으로 다시로드하도록 지시 할 수 있습니다 .

kill -HUP <pid>

(자세한 내용은 FAQ 참조)

Supervisor사용 하여 Gunicorn 서버를 제어하므로 배포 후 Gunicorn을 다시로드하는이 방법 (약간 해키)을 사용할 수 있습니다.

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

pidof, 또는와 비슷한 것을 분명히 얻을 수 ps있습니다.

이것은 실제로 Fabric 스크립트 에서 실행 되므로 서버에 로그온 할 필요조차 없습니다.


supervisord를 사용하지 않는 사람들을 위해 : Rob이 말한 것처럼 ps에서도 작동합니다.

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

Systemd, gunicorn 및 Ubuntu

systemd를 사용 하여 gunicorn 서비스를 실행하는 경우 한 줄짜리가 있습니다 .

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

단계별 세부 정보

이후 gunicorn의 문서가 정상적으로 노동자를 다시로드에 대한 올바른 방법은 사용하는 것입니다 말할 kill -HUP <Main PID>경우, <Main PID>마스터 프로세스의 프로세스 ID, 우리는 systemctl하고 실행을 사용하여 마스터 PID를 추출 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) 기본 gunicorn 프로세스의 프로세스 ID (PID)를 가져옵니다.

나오지도 다음과 같은 명령이 작동합니다 :sed 's/<search this>/<replace with this>/g'

  • s means for the substitute command, and g means that search the whole input globally.
  • The -n flag tells sed not to print every line (or actually, not to print anything.)
  • The p at the end tells sed to print the matched line.
  • We search for .*Main PID: \(.*\)$, which is a regular expression pattern, which has following parts: .* matches any character (.) zero or more times (*). Then we search for Main PID: followed by any characters, repeated zero or more times (.*). To capture all characters after the Main PID:-text, we enclose the .* into parenthesis, which are escaped with backslashes: \(.*\). $ indicates line end.
  • The "replace with this" part of the sed command is just \1, which means the first captured set of characters.

Example output:

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

3) Get rid of the extra characters

Pipe the output to cut. The cut -f1 -d' ' means, that

  • The string is space delimited: Here -d determines the delimiter, which is the characted just after the -d. Since the delimiter is space, we enclose that in quotes.
  • -f means just that cutting is made using the delimiter (and not by bytes), and -f1 means that we want to take out the first element of the list.

Example output:

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

4) Use the Main PID

Piping to xargs means just running the command with arguments from the pipe on the left hand side. Since we are piping just the Main PID to xargs,

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

is basically just the same thing as

echo <Main PID > | xargs kill -HUP

which translates into

kill -HUP <Main PID >

Edit

A little more robust solution would be to use cut -f1 -d$'\n' or grep -m1 "" in front of cut -f1 -d' ', to pick just the first line of the match. I can't figure out any circumstances, where there would be two matches for the Main PID:, though.


We run Gunicorn under Supervisor, but this is the simplest, cleanest way we've found to gracefully reload Gunicorn when it gets confused:

sudo pkill -HUP -f gunicorn.*master

Maybe not a direct answer to the question, but for those who are just looking for a way to restart gunicorn web server, you can use killall gunicorn and then execute a command to start gunicorn again. For example:

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

Note: killall gunicorn will terminate all gunicorn processes immediately so make sure you understand what you are doing.

ReferenceURL : https://stackoverflow.com/questions/9881819/a-better-way-to-restart-reload-gunicorn-via-upstart-after-git-pulling-my-dja

반응형