平滑升级Nginx的Shell脚本

时间:2022-12-05 00:13:39

        Nginx平滑升级说明,来自《Nginx Http Server - Updating Nginx gracefully》,这里不进行翻译了,原文如下:

        There are many situations where you need to replace the Nginx binary, for example, when you compile a new version and wish to put it in production or simply after having enabled new modules and rebuilt the application. What most administrators would do in this situation is stop the server, copy the new binary over the old one, and start Nginx again. While this is not considered to be a problem for most websites, there may be some cases where uptime is critical and connection losses should be avoided at all costs. Fortunately, Nginx embeds a mechanism allowing you to switch binaries with uninterrupted uptime - zero percent request loss is guaranteed if you follow these steps carefully:

       1. Replace the old Nginx binary( by default, /usr/local/nginx/sbin/nginx) with the new one.

       2. Find the pid of the Nginx master process, for example, with  ps x | grep nginx | grep master or by looking at the value found in the pid file.

       3. Send a USR2 signal to the master process - kill -USR2 ***, replacing ***  with the pid found in step 2. This will initiate the upgrade by renaming
the old  .pid file and running the new binary.

       4. Send a WINCH (28) signal to the old master process—kill –WINCH ***, replacing ***  with the pid found in step 2. This will engage a graceful
shutdown of the old worker processes.

       5. Make sure that all the old worker processes are terminated, and then send a QUIT signal to the old master process—kill –QUIT ***, replacing  ***  with the pid found in step 2.


Shell脚本如下:

#!/bin/sh

# 进行nginx软件平滑升级的shell脚本

# 提示更新nginx文件
echo -e '首先更新nginx文件,然后[回车]继续'
read yes
#if [ "$yes" != "Y" -o "$yes" != "y"]; then
# echo "未成功升级nginx"
# exit 100
#fi

# 记录master process的pid
old_master_pid=`ps -ef | grep 'nginx: master process' | grep -v ' grep ' | awk '{print $2}'`
echo 'master pid:' $old_master_pid

# 记录worker process的pid
old_workers_pid=`ps -ef | grep 'nginx: worker process' | grep -v ' grep ' | awk '{print $2}'`
echo 'worker process pid:' $old_workers_pid

# 向nginx发送USR2信号,重命名.pid为.pid.old,并启动新的nginx
kill -USR2 $old_master_pid

# 向nginx发送WINCH信号,平滑处理已链接请求
kill -WINCH $old_master_pid

# 等待旧的worker process是否全部退出
isOldWorkerProcessAllExit='yes'
while true
do
cur_workers_pid=`ps -ef | grep 'nginx: worker process' | grep -v ' grep ' | awk '{print $2}'`
# 判断旧的worker process进程是否退出,如果全部退出,则跳出循环
for pid in $old_workers_pid
do
subIndex=`awk 'BEGIN{print match("'"$cur_workers_pid"'","'"$pid"'")}'`
if [ "$subIndex" -ne "0" ]; then
isOldWorkerProcessAllExit="no"
break
fi
done
if [ "$isOldWorkerProcessAllExit" == "yes" ]; then
break
fi

sleep 1
done

# 向旧的master process发送QUIT信号,使其退出
kill -QUIT $old_master_pid

echo "nginx升级成功!"

exit 0