我有一个在乘客和nginx上运行的rails应用程序,有一个主要的web服务器和多个应用程序服务器。 我试图更新我的部署过程,以最大限度地减less(或理想情况下,删除)由部署造成的任何停机时间。 现在的主要障碍是乘客需要一些时间来重新启动(即重新加载应用程序),所以为了解决这个问题,我想错开重新启动,以便一次只有一个应用程序服务器重新启动。
为了做到这一点,而不会丢失任何长时间运行的乘客进程,我想我需要优雅地closures应用程序服务器的nginx实例,这将导致它不再接受新的连接,但继续处理现有的连接; 同样,HAProxy将检测到应用程序服务器已closures,并将新请求路由到其他服务器。
但是,假设有一个长期运行的过程,我不知道如何检测正常关机何时完成,以便我可以启动备份。 由于关机是由发送信号(即kill -QUIT $( cat /var/run/nginx.pid ) )导致的,kill命令将立即返回,所以我不能合并命令(即kill ... && touch restarted ),因为touch命令将立即执行,即使nginx尚未完成closures。
有没有什么好办法做到这一点?
这样的事情呢?
while [ -n "$(pgrep nginx)" ] do some-stuff done
所以,pgrep会寻找任何nginx进程,while循环会让它坐在那里直到它们全部消失。 你可以改变一些东西来做一些有用的事情,比如sleep 1; /etc/init.d/nginx stop sleep 1; /etc/init.d/nginx stop ,这样它会睡一会儿,然后尝试使用init.d脚本停止nginx。 你也可以在这个地方放一个计数器,这样如果计数时间太长,你可以发出重复的杀死信号。
基于cjc的回答 ,这里是我创build的bash脚本,以防其他人遇到同样的问题:
#!/bin/bash set -e if [[ $(/usr/bin/id -u) -ne 0 ]]; then echo "This script must be run as root." exit fi if [ -n "$(pgrep nginx)" -a -f /var/run/nginx.pid ]; then PID=$( cat /var/run/nginx.pid ) # Gracefully shutdown nginx kill -QUIT $PID # Wait for nginx to stop while [ -d "/proc/$PID" -a -f /var/run/nginx.pid ]; do sleep 1 done # Restart nginx /usr/sbin/service nginx start else echo "nginx is not running." exit 1 fi
你可以检查/ proc / $(cat /var/run/nginx.pid)/是否存在。 或者尝试查看/var/run/nginx.pid是否在closures时被删除。
ps -fC nginx
根7146 1 0 02:19? 00:00:00 nginx:主进程/ usr / sbin / nginx 1. www 7147 7146 0 02:19? 00:00:00 nginx:工作进程 2. www 7148 7146 0 02:19? 00:00:00 nginx:工作进程
所以如果你写一个closures/重新启动脚本,直到在这种情况下7146已经死亡,然后重新启动nginx