每次发出sudo restart projectname
时,我都会寻找比git pull origin master
更好的东西,这会将我对Django项目的最新更改下拉。我相信这个restart
命令与Upstart有关,我用它来启动/支持我的Gunicorn服务器进程。
此重新启动会导致短暂停机。击中Web服务器(nginx)的用户将获得500,因为Gunicorn仍在重启。事实上,它似乎立即重启,但页面加载需要几秒钟。
有关如何实现这一目标的任何想法?理想情况下,我想自动发出git pull
和Gunicorn重新加载。
答案 0 :(得分:80)
你可以告诉Gunicorn使用HUP
信号正常重新加载:
kill -HUP <pid>
(有关详细信息,请参阅FAQ)
我使用Supervisor来控制我的Gunicorn服务器,这允许我在部署后使用这种(略微hacky)方式重新加载Gunicorn:
supervisorctl status gunicorn | sed "s/.*[pid ]\([0-9]\+\)\,.*/\1/" | xargs kill -HUP
您显然可以通过pidof
或ps
实现类似的功能。
这实际上是从Fabric脚本运行的,所以我根本不需要登录服务器。
答案 1 :(得分:24)
对于那些不使用supervisord的人:Rob说,它也适用于ps,
ps aux |grep gunicorn |grep projectname | awk '{ print $2 }' |xargs kill -HUP
答案 2 :(得分:16)
为了优雅地重新加载,您应该使用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)。
答案 3 :(得分:7)
如果你使用 systemd 运行你的gunicorn服务,这是单线程。
systemctl status gunicorn | sed -n 's/.*Main PID: \(.*\)$/\1/g p' | cut -f1 -d' ' | xargs kill -HUP
由于gunicorn docs告诉正确重新加载worker的正确方法是使用kill -HUP <Main PID>
,其中<Main PID>
是主进程的进程ID,我们使用提取主PID systemctl,然后运行kill -HUP <Main PID>
。
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
sed 命令的工作原理如下:sed 's/<search this>/<replace with this>/g'
s
表示替换命令,而g
表示全局搜索 。-n
标志告诉sed 不打印每一行(或实际上,不打印任何内容。)p
告诉sed 打印匹配的行。.*Main PID: \(.*\)$
,这是一个正则表达式模式,其中包含以下部分:.*
匹配任何字符(.
)零次或多次(*
) 。然后我们搜索Main PID:
后跟任何字符,重复零次或多次(.*
)。要在Main PID:
- 文本之后捕获所有字符,我们将.*
括在括号中,这些括号使用反斜杠进行转义:\(.*\)
。 $
表示行结束。\1
,这意味着第一个捕获的字符集。示例输出:
ubuntu@ip-10-4-12-247:~$ systemctl status gunicorn | sed -n 's/.*Main PID: \(.*\)$/\1/g p'
10673 (gunicorn)
将输出传递给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
管道到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 >
更强大的解决方案是在cut -f1 -d$'\n'
前面使用grep -m1 ""
或cut -f1 -d' '
来挑选匹配的第一行。我无法弄清楚任何情况,但Main PID:
会有两个匹配。
答案 4 :(得分:2)
我们在Supervisor下运行Gunicorn,但这是我们发现的最简单,最干净的方式,当它被混淆时优雅地重新加载Gunicorn:
sudo pkill -HUP -f gunicorn.*master
答案 5 :(得分:2)
也许不是该问题的直接答案,但是对于那些只想重启gunicorn
Web服务器的人,您可以使用killall gunicorn
然后执行命令以重新启动gunicorn。例如:
killall gunicorn
gunicorn --bind 0.0.0.0:80 --reload app:app
注意: killall gunicorn
将立即终止所有gunicorn流程,因此请确保您了解自己在做什么。
答案 6 :(得分:2)
sudo systemctl restart gunicorn
答案 7 :(得分:0)
使用cmd重新启动gunicorn服务
systemctl restart gunicorn
否则,重新启动gunicorn服务并再次创建袜子文件。
答案 8 :(得分:0)
如果您在端口而不是套接字上运行 gunicorn
,则可以
使用fuser命令找到gunicorn的进程ID(pid)。然后通过发送HUP
信号来强制使用枪械来重新加载代码。
命令fuser 8000/tcp
将列出使用tcp端口8000的所有进程的进程ID。
fuser -k 8000/tcp
将毫不客气地杀死那些进程,这是不推荐的。
fuser -k -HUP 8000/tcp
将使用tcp端口9000强制使用
通过发送HUP信号重新加载代码。