Плавное обновление nginx

После ручной сборки nginx из исходных кодов выполнение перезапуска веб-сервера приведет к ошибке о занятом интерфейсе:

nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)

Так происходит потому, что скрипт запуска (/etc/init.d/nginx) не обнаруживает в памяти запущенного рабочего процесса новой версии, а на старый не обращает внимания.

Можно жестко завершить дерево старых процессов, а затем запустить новый, с помощью последовательного выполнения команд

kill `pidof nginx`
/etc/init.d/nginx restart

Более правильным способом обновления версии запущенного веб-сервера является замена рабочих процессов на лету. Для этого:

  1. Находим главный процесс с припиской в названии master:
    ps axu|grep nginx

    nginx-ps

  2. Отправляем этому процессу сигнал USR2, который укажет master-процессу переименовать свой файл с номером процесса в файл с суффиксом .oldbin, например, /var/run/nginx.pid.oldbin, после чего запустит новый исполняемый файл, а тот в свою очередь — свои рабочие процессы:
    kill -USR2 21248
    ps axu|grep nginx

    nginx-ps-2

  3. Теперь, если послать сигнал WINCH первому главному процессу, то он пошлёт своим рабочим процессам сообщение о плавном выходе, и они будут постепенно выходить.
    kill -WINCH 21248

    В результате в системе останется запущено 2 главных процесса и новые принимающие соединения рабочие процессы. Старый master-процесс в случае успешной обновленной версии можно завершить:

    kill -QUIT 21248

Если новый исполняемый файл работает некорректно, можно вместо завершения работы старого третьим пунктом выполнить любой из следующих:

  • Послать старому главному процессу сигнал HUP (по аналогии с предыдущими командами). Старый главный процесс, не перечитывая конфигурации, запустит новые рабочие процессы. После этого можно плавно завершить все новые процессы, послав новому главному процессу сигнал QUIT.
  • Послать новому главному процессу сигнал TERM. В ответ на это он пошлёт сообщение о немедленном выходе своим рабочим процессам, и все они практически сразу же завершатся. (Если новые процессы по каким-то причинам не завершаются, нужно послать им сигнал KILL, который заставит их завершиться.) По завершению нового главного процесса старый главный процесс автоматически запустит новые рабочие процессы.

Ссылки: