有没有什么方法可以检测 nginx 何时完成了正常关闭?

有没有什么方法可以检测 nginx 何时完成了正常关闭?

我有一个在 Passenger 和 nginx 上运行的 ruby​​ on rails 应用程序,它有一个主 Web 服务器和多个应用程序服务器。我正在尝试更新我的部署过程,以尽量减少(或理想情况下消除)部署造成的任何停机时间。目前的主要障碍是 Passenger 需要一些时间才能重新启动(即重新加载应用程序),因此为了解决这个问题,我想错开我的重新启动,以便一次只重新启动一个应用服务器。

为了做到这一点而不丢失任何长时间运行的乘客进程,我想我需要正常关闭应用服务器的 nginx 实例,这将导致它不再接受新连接但继续处理现有连接;此外,HAProxy 将检测到应用服务器已关闭并将新请求路由到另一台服务器。

但是,假设有一个长时间运行的进程,我不确定如何检测正常关闭何时完成,以便我可以重新启动它。由于关闭是由发送信号(即kill -QUIT $( cat /var/run/nginx.pid ))引起的,并且 kill 命令将立即返回,因此我无法组合命令(即kill ... && touch restarted),因为touch即使 nginx 尚未完成关闭,该命令也会立即执行。

有什么好方法可以做到这一点吗?

答案1

那么像这样的事情怎么办?

while [ -n "$(pgrep nginx)" ]
do
  some-stuff  
done

因此,pgrep 将查找任何 nginx 进程,而 while 循环将让它停留在那里,直到它们全部消失。您可以更改某些内容以执行一些有用的操作,例如sleep 1; /etc/init.d/nginx stop,以便它会休眠一秒钟,然后尝试使用 init.d 脚本停止 nginx。您还可以在其中某处放置一个计数器,以便在花费时间太长时发出终止信号。

答案2

为什么不使用内置标志来实现这一点?

nginx -s quit

读取第二个块,其中有此标志的解释......

http://nginx.org/en/docs/control.html

答案3

基于cjc 的回答,下面是我创建的 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

答案4

ps -fC nginx

  root 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:工作进程

因此,如果你编写一个关闭/重启脚本,循环执行,直到 7146 停止运行,然后再次重启 nginx

相关内容