web-dev-qa-db-ja.com

my Djangoプロジェクトを 'git pull'した後、Gunicornを(Upstart経由で)再起動/リロードするより良い方法

Sudo restart projectnameを発行するたびにgit pull Origin masterよりも良いものを探しています。これはDjangoプロジェクトへの私の最新の変更をプルダウンします。このrestartコマンドは、Gstartサーバープロセスを開始/開始するために使用するUpstartに関連していると思います。

この再起動により、短時間の停止が発生します。 Gunicornがまだ再起動しているため、Webサーバー(nginx)にアクセスするユーザーには500が表示されます。実際、すぐに再起動するようですが、ページの読み込みには数秒かかります。

これをシームレスにする方法に関するアイデアはありますか?理想的には、git pullを発行し、Gunicornを自動的にリロードしたいと思います。

54
Flowpoke

正常にリロードするには、代わりにUpstartのreloadコマンドを使用する必要があります。例:

Sudo reload jobname

Initctl(Upstart) manpage によると、reloadHUPシグナルをプロセスに送信します。

reload JOB [KEY=VALUE]...

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

...これはGunicornの場合、グレースフルリスタートをトリガーします( [〜#〜] faq [〜#〜] を参照)。

17
Gary

次のようにHUPシグナルを使用してGunicornに正常にリロードするように指示できます。

kill -HUP <pid>

(詳細については [〜#〜] faq [〜#〜] を参照してください)

Supervisor を使用してGunicornサーバーを制御します。これにより、デプロイ後にGunicornをリロードするこの(少しハッキングな)方法を使用できます。

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

明らかにpidofまたはpsで同様のことを達成できます。

これは実際には Fabric スクリプトから実行されるため、サーバーにログオンする必要さえありません。

81
Rob Golding

スーパーバイザーを使用していない場合:ロブが言ったように、psでも動作します。

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

Systemd、gunicorn、Ubuntu

systemdを使用してgunicornサービスを実行している場合、1行になります。

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

ステップごとの詳細

gunicorn docs は、ワーカーを正常にリロードする正しい方法は_kill -HUP <Main PID>_を使用することであると言うため(ここで_<Main PID>_はマスタープロセスのプロセスIDです)、マスター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)メインのgunicornプロセスのプロセスID(PID)を取得する

sedコマンドは次のように機能します:_sed 's/<search this>/<replace with this>/g'_

  • ssubstituteコマンドを意味し、gは入力全体をグローバルに検索することを意味します
  • _-n_フラグは、sednotにすべての行を印刷する(または実際には何も印刷しない)ように指示します。
  • 末尾のpは、sedに一致した行を印刷するよう指示します
  • 正規表現パターンである.*Main PID: \(.*\)$を検索します。次の部分があります。_.*_は、任意の文字(_._)に0回以上一致します(_*_)。次に、_Main PID:_に続いて任意の文字を検索し、ゼロ回以上繰り返します(_.*_)。 _Main PID:_- textの後のすべての文字をキャプチャするには、_.*_を括弧で囲みます。括弧は、バックスラッシュ\(.*\)でエスケープされます。 _$_は行末を示します。
  • Sedコマンドの「これに置き換え」の部分は_\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を使用する

xargs へのパイプは、左側のパイプから引数を指定してコマンドを実行することを意味します。 Main 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 >
_

編集

もう少し堅牢なソリューションは、_cut -f1 -d$'\n'_の前に_grep -m1 ""_または_cut -f1 -d' '_を使用して、一致の最初の行だけを選択することです。ただし、_Main PID:_に2つの一致がある状況を把握することはできません。

7
np8

質問に対する直接的な答えではないかもしれませんが、gunicorn Webサーバーを再起動する方法を探しているだけの人には、killall gunicornその後、コマンドを実行してgunicornを再度起動します。例えば:

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

注:killall gunicornはすべてのgunicornプロセスを即座に終了しますので、あなたが何をしているかを理解してください。

Gunicornをスーパーバイザーの下で実行しますが、これは混乱した場合にGunicornを正常にリロードすることがわかった最も簡単でクリーンな方法です。

Sudo pkill -HUP -f gunicorn.*master
2
johntellsall